add chart to PDF command engine, add svg salamander parser
This commit is contained in:
parent
08686de066
commit
683ab49c83
126 changed files with 42955 additions and 21 deletions
|
@ -11,10 +11,6 @@ import java.util.List;
|
|||
*/
|
||||
public final class QuickChart {
|
||||
|
||||
private final static int WIDTH = 600;
|
||||
|
||||
private final static int HEIGHT = 400;
|
||||
|
||||
private QuickChart() {
|
||||
}
|
||||
|
||||
|
@ -23,12 +19,14 @@ public final class QuickChart {
|
|||
String yTitle,
|
||||
String seriesName,
|
||||
double[] xData,
|
||||
double[] yData) {
|
||||
double[] yData,
|
||||
int width,
|
||||
int height) {
|
||||
double[][] yData2d = { yData };
|
||||
if (seriesName == null) {
|
||||
return getChart(chartTitle, xTitle, yTitle, null, xData, yData2d);
|
||||
return getChart(chartTitle, xTitle, yTitle, null, xData, yData2d, width, height);
|
||||
} else {
|
||||
return getChart(chartTitle, xTitle, yTitle, new String[]{seriesName}, xData, yData2d);
|
||||
return getChart(chartTitle, xTitle, yTitle, new String[]{seriesName}, xData, yData2d, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,8 +35,10 @@ public final class QuickChart {
|
|||
String yTitle,
|
||||
String[] seriesNames,
|
||||
double[] xData,
|
||||
double[][] yData) {
|
||||
XYChart chart = new XYChart(WIDTH, HEIGHT);
|
||||
double[][] yData,
|
||||
int width,
|
||||
int height) {
|
||||
XYChart chart = new XYChart(width, height);
|
||||
chart.setTitle(chartTitle);
|
||||
chart.setXAxisTitle(xTitle);
|
||||
chart.setYAxisTitle(yTitle);
|
||||
|
@ -60,8 +60,10 @@ public final class QuickChart {
|
|||
String yTitle,
|
||||
String seriesName,
|
||||
List<? extends Double> xData,
|
||||
List<? extends Double> yData) {
|
||||
XYChart chart = new XYChart(WIDTH, HEIGHT);
|
||||
List<? extends Double> yData,
|
||||
int width,
|
||||
int height) {
|
||||
XYChart chart = new XYChart(width, height);
|
||||
chart.setTitle(chartTitle);
|
||||
chart.setXAxisTitle(xTitle);
|
||||
chart.setYAxisTitle(yTitle);
|
||||
|
|
|
@ -16,7 +16,7 @@ public class QuickChartTest {
|
|||
double[] xData = new double[] { 0.0, 1.0, 2.0 };
|
||||
double[] yData = new double[] { 2.0, 1.0, 0.0 };
|
||||
XYChart chart = QuickChart.getChart("Sample Chart",
|
||||
"X", "Y", "y(x)", xData, yData);
|
||||
"X", "Y", "y(x)", xData, yData, 640, 480);
|
||||
chart.write(Files.newOutputStream(Paths.get("build/quickchart1.pdf")),
|
||||
VectorGraphicsFormat.PDF);
|
||||
}
|
||||
|
|
|
@ -115,18 +115,16 @@ public class ChartElement implements Element, Drawable, Dividable, WidthRespecti
|
|||
float x = upperLeft.getX();
|
||||
float y = upperLeft.getY() - getHeight();
|
||||
PdfBoxGraphics2D pdfBoxGraphics2D = new PdfBoxGraphics2D(pdDocument, getWidth(), getHeight());
|
||||
Logger.getLogger("").info("x=" + x + " y=" + y);
|
||||
Logger.getLogger("").info("xData=" + Arrays.toString(xData));
|
||||
Logger.getLogger("").info("yData=" + Arrays.toString(xData));
|
||||
XYChart chart = QuickChart.getChart("Sample Chart",
|
||||
"X", "Y", "y(x)", xData, yData);
|
||||
chart.paint(pdfBoxGraphics2D, 600, 480);
|
||||
XYChart chart = QuickChart.getChart("Hello Jörg",
|
||||
"X", "Y", "y(x)", xData, yData, (int) getWidth(), (int) getHeight());
|
||||
chart.paint(pdfBoxGraphics2D, (int) getWidth(), (int) getHeight());
|
||||
PDFormXObject xFormObject = pdfBoxGraphics2D.getXFormObject();
|
||||
xFormObject.setMatrix(AffineTransform.getTranslateInstance(x, y));
|
||||
//Matrix matrix = new Matrix();
|
||||
//matrix.translate(x, y);
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.translate(x, y);
|
||||
matrix.scale(scaleX, scaleY);
|
||||
contentStream.saveGraphicsState();
|
||||
//contentStream.transform(matrix);
|
||||
contentStream.transform(matrix);
|
||||
contentStream.drawForm(xFormObject);
|
||||
contentStream.restoreGraphicsState();
|
||||
if (drawListener != null) {
|
||||
|
|
|
@ -104,6 +104,17 @@
|
|||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "chart",
|
||||
"x": 0,
|
||||
"y": 150,
|
||||
"width": 600,
|
||||
"height": 480,
|
||||
"scalex": 0.66,
|
||||
"scaley": 0.66,
|
||||
"xdata": [ 0.0, 1.0, 3.0, 7.0 ],
|
||||
"ydata": [ 3.5, 2.5, 1.25, 0.8 ]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
109
graphics-svg/src/main/java/org/xbib/graphics/svg/A.java
Normal file
109
graphics-svg/src/main/java/org/xbib/graphics/svg/A.java
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 1:56 AM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class A extends Group
|
||||
{
|
||||
public static final String TAG_NAME = "a";
|
||||
|
||||
URI href;
|
||||
String title;
|
||||
|
||||
/** Creates a new instance of Stop */
|
||||
public A()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("xlink:href")))
|
||||
{
|
||||
href = sty.getURIValue(getXMLBase());
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("xlink:title")))
|
||||
{
|
||||
title = sty.getStringValue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event.
|
||||
* Ie, all attributes with track information.
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("xlink:href")))
|
||||
{
|
||||
href = sty.getURIValue(getXMLBase());
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("xlink:title")))
|
||||
{
|
||||
title = sty.getStringValue();
|
||||
}
|
||||
|
||||
return changeState;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,215 @@
|
|||
package org.xbib.graphics.svg;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BufferPainter
|
||||
{
|
||||
public static final boolean DEBUG_PAINT = false;
|
||||
|
||||
public static class Cache
|
||||
{
|
||||
private final BufferedImage img;
|
||||
private final Rectangle bounds;
|
||||
private final AffineTransform transform;
|
||||
|
||||
public Cache(BufferedImage img, Rectangle bounds, AffineTransform transform)
|
||||
{
|
||||
this.img = img;
|
||||
this.bounds = bounds;
|
||||
this.transform = transform;
|
||||
}
|
||||
|
||||
boolean isCompatible(AffineTransform tx)
|
||||
{
|
||||
return tx.getScaleX() == transform.getScaleX()
|
||||
&& tx.getScaleY() == transform.getScaleY()
|
||||
&& tx.getShearX() == transform.getShearX()
|
||||
&& tx.getShearY() == transform.getShearY();
|
||||
}
|
||||
|
||||
Rectangle getBoundsForTransform(AffineTransform tx)
|
||||
{
|
||||
double dx = tx.getTranslateX() - transform.getTranslateX();
|
||||
double dy = tx.getTranslateY() - transform.getTranslateY();
|
||||
return new Rectangle((int) (bounds.x + dx), (int) (bounds.y + dy),
|
||||
bounds.width, bounds.height);
|
||||
}
|
||||
}
|
||||
|
||||
public static void paintElement(Graphics2D g, RenderableElement element) throws SVGException
|
||||
{
|
||||
if (element.cachedMask != null
|
||||
|| (element.filter != null && !element.filter.filterEffects.isEmpty()))
|
||||
{
|
||||
renderElement(g, element);
|
||||
} else
|
||||
{
|
||||
element.doRender(g);
|
||||
}
|
||||
}
|
||||
|
||||
private static float getTransformScale(Point2D.Float origin, Point2D.Float testPoint,
|
||||
AffineTransform transform)
|
||||
{
|
||||
transform.transform(testPoint, testPoint);
|
||||
float dx = testPoint.x - origin.x;
|
||||
float dy = testPoint.y - origin.y;
|
||||
return (float) Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
private static void renderElement(Graphics2D g, RenderableElement element) throws SVGException
|
||||
{
|
||||
AffineTransform transform = g.getTransform();
|
||||
|
||||
Graphics2D gg = (Graphics2D) g.create();
|
||||
Rectangle elementBounds = element.getBoundingBox().getBounds();
|
||||
Rectangle transformedBounds = transform.createTransformedShape(elementBounds).getBounds();
|
||||
Rectangle dstBounds = new Rectangle(transformedBounds);
|
||||
|
||||
ImageObserver observer = element.diagram.getCurrentRenderTarget();
|
||||
|
||||
Cache cache = element.getBufferCache();
|
||||
BufferedImage elementImage;
|
||||
|
||||
if (cache == null || observer == null || !cache.isCompatible(transform))
|
||||
{
|
||||
elementImage = renderToBuffer(gg, element, transform, transformedBounds, dstBounds);
|
||||
if (observer != null)
|
||||
{
|
||||
// Only do caching if we are painting to a component.
|
||||
Cache cacheEntry = new Cache(elementImage, new Rectangle(dstBounds), transform);
|
||||
element.setBufferImage(cacheEntry);
|
||||
}
|
||||
} else
|
||||
{
|
||||
elementImage = cache.img;
|
||||
dstBounds.setBounds(cache.getBoundsForTransform(transform));
|
||||
}
|
||||
|
||||
// Reset the transform. We already accounted for it in the buffer image.
|
||||
gg.setTransform(new AffineTransform());
|
||||
gg.drawImage(elementImage, dstBounds.x, dstBounds.y, observer);
|
||||
if (DEBUG_PAINT)
|
||||
{
|
||||
gg.setColor(Color.GREEN);
|
||||
gg.drawRect(dstBounds.x, dstBounds.y, dstBounds.width, dstBounds.height);
|
||||
if (!dstBounds.equals(transformedBounds))
|
||||
{
|
||||
gg.setColor(Color.PINK);
|
||||
gg.drawRect(transformedBounds.x, transformedBounds.y, transformedBounds.width, transformedBounds.height);
|
||||
}
|
||||
}
|
||||
gg.dispose();
|
||||
}
|
||||
|
||||
private static BufferedImage renderToBuffer(Graphics2D gg, RenderableElement element,
|
||||
AffineTransform transform, Rectangle transformedBounds,
|
||||
Rectangle dstBounds) throws SVGException
|
||||
{
|
||||
Point2D.Float origin = new Point2D.Float(0, 0);
|
||||
transform.transform(origin, origin);
|
||||
|
||||
// As filter operations are commonly implemented using convolutions they need to be
|
||||
// aware of any possible scaling to compensate for it in their kernel size.
|
||||
Point2D.Float testPoint = new Point2D.Float(1, 0);
|
||||
float xScale = getTransformScale(origin, testPoint, transform);
|
||||
testPoint.setLocation(0, 1);
|
||||
float yScale = getTransformScale(origin, testPoint, transform);
|
||||
|
||||
List<FilterEffects.FilterOp> filterOps = element.filter == null
|
||||
? Collections.emptyList()
|
||||
: element.filter.filterEffects.stream()
|
||||
.flatMap(f -> f.getOperations(dstBounds, xScale, yScale).stream())
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (FilterEffects.FilterOp filterOp : filterOps)
|
||||
{
|
||||
int right = Math.max(dstBounds.x + dstBounds.width,
|
||||
filterOp.requiredImageBounds.x + filterOp.requiredImageBounds.width);
|
||||
int bottom = Math.max(dstBounds.y + dstBounds.height,
|
||||
filterOp.requiredImageBounds.y + filterOp.requiredImageBounds.height);
|
||||
dstBounds.x = Math.min(dstBounds.x, filterOp.requiredImageBounds.x);
|
||||
dstBounds.y = Math.min(dstBounds.y, filterOp.requiredImageBounds.y);
|
||||
dstBounds.width = right - dstBounds.x;
|
||||
dstBounds.height = bottom - dstBounds.y;
|
||||
}
|
||||
|
||||
|
||||
BufferedImage elementImage = BufferPainter.paintToBuffer(gg, transform, dstBounds, transformedBounds,
|
||||
element, null, true);
|
||||
|
||||
for (FilterEffects.FilterOp filterOp : filterOps)
|
||||
{
|
||||
elementImage = filterOp.op.filter(elementImage, null);
|
||||
}
|
||||
|
||||
if (element.cachedMask != null)
|
||||
{
|
||||
// Draw the mask image. Implicitly the mask is empty i.e. has a completely black background.
|
||||
// We can't draw the mask directly to the elementImage using the mask composite as
|
||||
// masks may change the mask value a location at any time during mask realization.
|
||||
BufferedImage maskImage = BufferPainter.paintToBuffer(gg, transform, dstBounds, transformedBounds,
|
||||
element.cachedMask, Color.BLACK, false);
|
||||
|
||||
Graphics2D elementGraphics = (Graphics2D) elementImage.getGraphics();
|
||||
elementGraphics.setRenderingHints(gg.getRenderingHints());
|
||||
elementGraphics.setComposite(element.cachedMask.createMaskComposite());
|
||||
elementGraphics.drawImage(maskImage, 0, 0, element.diagram.getCurrentRenderTarget());
|
||||
elementGraphics.dispose();
|
||||
}
|
||||
return elementImage;
|
||||
}
|
||||
|
||||
public static BufferedImage paintToBuffer(Graphics2D g, AffineTransform transform,
|
||||
Rectangle srcBounds, RenderableElement element,
|
||||
Color bgColor) throws SVGException
|
||||
{
|
||||
return paintToBuffer(g, transform, srcBounds, srcBounds, element, bgColor, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* The srcBounds parameter is expected to be pre-transformed by the given transform.
|
||||
*/
|
||||
public static BufferedImage paintToBuffer(Graphics2D g, AffineTransform transform,
|
||||
Rectangle dstBounds, Rectangle srcBounds,
|
||||
RenderableElement element,
|
||||
Color bgColor, boolean preMultiplied) throws SVGException
|
||||
{
|
||||
int type = preMultiplied
|
||||
? BufferedImage.TYPE_INT_ARGB_PRE
|
||||
: BufferedImage.TYPE_INT_ARGB;
|
||||
BufferedImage img = new BufferedImage(dstBounds.width, dstBounds.height, type);
|
||||
Graphics2D imgGraphics = (Graphics2D) img.getGraphics();
|
||||
if (g != null)
|
||||
{
|
||||
imgGraphics.setRenderingHints(g.getRenderingHints());
|
||||
} else if (bgColor != null)
|
||||
{
|
||||
imgGraphics.setColor(bgColor);
|
||||
imgGraphics.fillRect(0, 0, img.getWidth(), img.getHeight());
|
||||
}
|
||||
int xRelative = srcBounds.x - dstBounds.x;
|
||||
int yRelative = srcBounds.y - dstBounds.y;
|
||||
imgGraphics.translate(xRelative, yRelative);
|
||||
imgGraphics.clipRect(0, 0, srcBounds.width, srcBounds.height);
|
||||
|
||||
// Because we blit the image at the transformed location we have to compensate for the
|
||||
// element location.
|
||||
imgGraphics.translate(-srcBounds.x, -srcBounds.y);
|
||||
imgGraphics.transform(transform);
|
||||
element.doRender(imgGraphics);
|
||||
imgGraphics.dispose();
|
||||
return img;
|
||||
}
|
||||
}
|
171
graphics-svg/src/main/java/org/xbib/graphics/svg/Circle.java
Normal file
171
graphics-svg/src/main/java/org/xbib/graphics/svg/Circle.java
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 5:25 PM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Circle extends ShapeElement
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "circle";
|
||||
float cx = 0f;
|
||||
float cy = 0f;
|
||||
float r = 0f;
|
||||
Ellipse2D.Float circle = new Ellipse2D.Float();
|
||||
|
||||
/**
|
||||
* Creates a new instance of Rect
|
||||
*/
|
||||
public Circle()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("cx")))
|
||||
{
|
||||
cx = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("cy")))
|
||||
{
|
||||
cy = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("r")))
|
||||
{
|
||||
r = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
circle.setFrame(cx - r, cy - r, r * 2f, r * 2f);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRender(Graphics2D g) throws SVGException
|
||||
{
|
||||
beginLayer(g);
|
||||
renderShape(g, circle);
|
||||
finishLayer(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getShape()
|
||||
{
|
||||
return shapeToParent(circle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBoundingBox() throws SVGException
|
||||
{
|
||||
return boundsToParent(includeStrokeInBounds(circle.getBounds2D()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean shapeChange = false;
|
||||
|
||||
if (getPres(sty.setName("cx")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != cx)
|
||||
{
|
||||
cx = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("cy")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != cy)
|
||||
{
|
||||
cy = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("r")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != r)
|
||||
{
|
||||
r = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shapeChange)
|
||||
{
|
||||
build();
|
||||
// circle.setFrame(cx - r, cy - r, r * 2f, r * 2f);
|
||||
// return true;
|
||||
}
|
||||
|
||||
return changeState || shapeChange;
|
||||
}
|
||||
}
|
174
graphics-svg/src/main/java/org/xbib/graphics/svg/ClipPath.java
Normal file
174
graphics-svg/src/main/java/org/xbib/graphics/svg/ClipPath.java
Normal file
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 1:56 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Area;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class ClipPath extends SVGElement
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "clippath";
|
||||
public static final int CP_USER_SPACE_ON_USE = 0;
|
||||
public static final int CP_OBJECT_BOUNDING_BOX = 1;
|
||||
int clipPathUnits = CP_USER_SPACE_ON_USE;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Stop
|
||||
*/
|
||||
public ClipPath()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the start element but before the end element to indicate
|
||||
* each child tag that has been processed
|
||||
*/
|
||||
@Override
|
||||
public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
|
||||
{
|
||||
super.loaderAddChild(helper, child);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
clipPathUnits = (getPres(sty.setName("clipPathUnits"))
|
||||
&& sty.getStringValue().equals("objectBoundingBox"))
|
||||
? CP_OBJECT_BOUNDING_BOX
|
||||
: CP_USER_SPACE_ON_USE;
|
||||
}
|
||||
|
||||
public int getClipPathUnits()
|
||||
{
|
||||
return clipPathUnits;
|
||||
}
|
||||
|
||||
public Shape getClipPathShape()
|
||||
{
|
||||
if (children.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (children.size() == 1)
|
||||
{
|
||||
return ((ShapeElement) children.get(0)).getShape();
|
||||
}
|
||||
|
||||
Area clipArea = null;
|
||||
for (SVGElement svgElement : children) {
|
||||
ShapeElement se = (ShapeElement) svgElement;
|
||||
|
||||
if (clipArea == null)
|
||||
{
|
||||
Shape shape = se.getShape();
|
||||
if (shape != null)
|
||||
{
|
||||
clipArea = new Area(se.getShape());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Shape shape = se.getShape();
|
||||
if (shape != null)
|
||||
{
|
||||
clipArea.intersect(new Area(shape));
|
||||
}
|
||||
}
|
||||
|
||||
return clipArea;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @param curTime Time at which to evaluate node
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
* @throws SVGException
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean shapeChange = false;
|
||||
|
||||
|
||||
if (getPres(sty.setName("clipPathUnits")))
|
||||
{
|
||||
String newUnitsStrn = sty.getStringValue();
|
||||
int newUnits = newUnitsStrn.equals("objectBoundingBox")
|
||||
? CP_OBJECT_BOUNDING_BOX
|
||||
: CP_USER_SPACE_ON_USE;
|
||||
|
||||
if (newUnits != clipPathUnits)
|
||||
{
|
||||
clipPathUnits = newUnits;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shapeChange)
|
||||
{
|
||||
build();
|
||||
}
|
||||
|
||||
for (int i = 0; i < children.size(); ++i)
|
||||
{
|
||||
SVGElement ele = (SVGElement) children.get(i);
|
||||
ele.updateTime(curTime);
|
||||
}
|
||||
|
||||
return shapeChange;
|
||||
}
|
||||
}
|
97
graphics-svg/src/main/java/org/xbib/graphics/svg/Defs.java
Normal file
97
graphics-svg/src/main/java/org/xbib/graphics/svg/Defs.java
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 1:56 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleSheet;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Defs extends TransformableElement
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "defs";
|
||||
|
||||
/**
|
||||
* Creates a new instance of Stop
|
||||
*/
|
||||
public Defs()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the start element but before the end element to indicate
|
||||
* each child tag that has been processed
|
||||
*/
|
||||
@Override
|
||||
public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
|
||||
{
|
||||
super.loaderAddChild(helper, child);
|
||||
|
||||
// members.add(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
boolean stateChange = false;
|
||||
for (SVGElement ele : children) {
|
||||
stateChange = stateChange || ele.updateTime(curTime);
|
||||
}
|
||||
|
||||
return super.updateTime(curTime) || stateChange;
|
||||
}
|
||||
|
||||
public StyleSheet getStyleSheet()
|
||||
{
|
||||
for (int i = 0; i < getNumChildren(); ++i)
|
||||
{
|
||||
SVGElement ele = getChild(i);
|
||||
if (ele instanceof Style)
|
||||
{
|
||||
return ((Style)ele).getStyleSheet();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
82
graphics-svg/src/main/java/org/xbib/graphics/svg/Desc.java
Normal file
82
graphics-svg/src/main/java/org/xbib/graphics/svg/Desc.java
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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 September 19, 2004, 1:56 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
/**
|
||||
* Holds title textual information within tree
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Desc extends SVGElement
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "desc";
|
||||
StringBuffer text = new StringBuffer();
|
||||
|
||||
/**
|
||||
* Creates a new instance of Stop
|
||||
*/
|
||||
public Desc()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during load process to add text scanned within a tag
|
||||
*/
|
||||
@Override
|
||||
public void loaderAddText(SVGLoaderHelper helper, String text)
|
||||
{
|
||||
this.text.append(text);
|
||||
}
|
||||
|
||||
public String getText()
|
||||
{
|
||||
return text.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTime(double curTime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
187
graphics-svg/src/main/java/org/xbib/graphics/svg/Ellipse.java
Normal file
187
graphics-svg/src/main/java/org/xbib/graphics/svg/Ellipse.java
Normal file
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 5:25 PM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Ellipse extends ShapeElement
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "ellipse";
|
||||
float cx = 0.0f;
|
||||
float cy = 0.0f;
|
||||
float rx = 0.0f;
|
||||
float ry = 0.0f;
|
||||
Ellipse2D.Float ellipse = new Ellipse2D.Float();
|
||||
|
||||
/**
|
||||
* Creates a new instance of Rect
|
||||
*/
|
||||
public Ellipse()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("cx")))
|
||||
{
|
||||
cx = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("cy")))
|
||||
{
|
||||
cy = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("rx")))
|
||||
{
|
||||
rx = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("ry")))
|
||||
{
|
||||
ry = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
ellipse.setFrame(cx - rx, cy - ry, rx * 2f, ry * 2f);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRender(Graphics2D g) throws SVGException
|
||||
{
|
||||
beginLayer(g);
|
||||
renderShape(g, ellipse);
|
||||
finishLayer(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getShape()
|
||||
{
|
||||
return shapeToParent(ellipse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBoundingBox() throws SVGException
|
||||
{
|
||||
return boundsToParent(includeStrokeInBounds(ellipse.getBounds2D()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean shapeChange = false;
|
||||
|
||||
if (getPres(sty.setName("cx")))
|
||||
{
|
||||
float newCx = sty.getFloatValueWithUnits();
|
||||
if (newCx != cx)
|
||||
{
|
||||
cx = newCx;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("cy")))
|
||||
{
|
||||
float newCy = sty.getFloatValueWithUnits();
|
||||
if (newCy != cy)
|
||||
{
|
||||
cy = newCy;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("rx")))
|
||||
{
|
||||
float newRx = sty.getFloatValueWithUnits();
|
||||
if (newRx != rx)
|
||||
{
|
||||
rx = newRx;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("ry")))
|
||||
{
|
||||
float newRy = sty.getFloatValueWithUnits();
|
||||
if (newRy != ry)
|
||||
{
|
||||
ry = newRy;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shapeChange)
|
||||
{
|
||||
build();
|
||||
// ellipse.setFrame(cx - rx, cy - ry, rx * 2f, ry * 2f);
|
||||
// return true;
|
||||
}
|
||||
|
||||
return changeState || shapeChange;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* 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 March 18, 2004, 6:52 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class FeDistantLight extends FeLight
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "fedistantlight";
|
||||
float azimuth = 0f;
|
||||
float elevation = 0f;
|
||||
|
||||
/**
|
||||
* Creates a new instance of FillElement
|
||||
*/
|
||||
public FeDistantLight()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("azimuth")))
|
||||
{
|
||||
azimuth = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("elevation")))
|
||||
{
|
||||
elevation = sty.getFloatValueWithUnits();
|
||||
}
|
||||
}
|
||||
|
||||
public float getAzimuth()
|
||||
{
|
||||
return azimuth;
|
||||
}
|
||||
|
||||
public float getElevation()
|
||||
{
|
||||
return elevation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean stateChange = false;
|
||||
|
||||
if (getPres(sty.setName("azimuth")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != azimuth)
|
||||
{
|
||||
azimuth = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("elevation")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != elevation)
|
||||
{
|
||||
elevation = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
return stateChange;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.ConvolveOp;
|
||||
import java.awt.image.Kernel;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class FeGaussianBlur extends FilterEffects
|
||||
{
|
||||
public static final String TAG_NAME = "fegaussianblur";
|
||||
|
||||
private float[] stdDeviation;
|
||||
private float xCurrent;
|
||||
private float yCurrent;
|
||||
private ConvolveOp xBlur;
|
||||
private ConvolveOp yBlur;
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
stdDeviation = new float[]{0f};
|
||||
if (getPres(sty.setName("stdDeviation")))
|
||||
{
|
||||
stdDeviation = sty.getFloatList();
|
||||
}
|
||||
xBlur = null;
|
||||
yBlur = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterOp> getOperations(Rectangle inputBounds, float xScale, float yScale)
|
||||
{
|
||||
float xSigma = xScale * stdDeviation[0];
|
||||
float ySigma = yScale * stdDeviation[Math.min(stdDeviation.length - 1, 1)];
|
||||
|
||||
return Arrays.asList(
|
||||
xSigma > 0
|
||||
? getGaussianBlurFilter(inputBounds, xSigma, true)
|
||||
: null,
|
||||
ySigma > 0
|
||||
? getGaussianBlurFilter(inputBounds, ySigma, false)
|
||||
: null
|
||||
);
|
||||
}
|
||||
|
||||
public FilterOp getGaussianBlurFilter(Rectangle inputBounds, float sigma, boolean horizontal)
|
||||
{
|
||||
int multiplier = 2;
|
||||
float radius = 2f * sigma + 1;
|
||||
int size = (int) Math.ceil(radius * multiplier) + 1;
|
||||
if (horizontal && (xBlur == null || xCurrent != sigma)
|
||||
|| !horizontal && (yBlur == null || yCurrent != sigma))
|
||||
{
|
||||
if (horizontal)
|
||||
{
|
||||
xCurrent = sigma;
|
||||
} else
|
||||
{
|
||||
yCurrent = sigma;
|
||||
}
|
||||
float[] data = new float[size];
|
||||
|
||||
float radius2 = radius * radius;
|
||||
float twoSigmaSquare = 2.0f * sigma * sigma;
|
||||
float sigmaRoot = (float) Math.sqrt(twoSigmaSquare * Math.PI);
|
||||
float total = 0.0f;
|
||||
|
||||
float middle = size / 2f;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
float distance = middle - i;
|
||||
distance *= distance;
|
||||
|
||||
data[i] = distance > radius2
|
||||
? 0
|
||||
: (float) Math.exp(-distance / twoSigmaSquare) / sigmaRoot;
|
||||
total += data[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < data.length; i++)
|
||||
{
|
||||
data[i] /= total;
|
||||
}
|
||||
|
||||
if (horizontal)
|
||||
{
|
||||
xBlur = new ConvolveOp(new Kernel(size, 1, data), ConvolveOp.EDGE_NO_OP, null);
|
||||
} else
|
||||
{
|
||||
yBlur = new ConvolveOp(new Kernel(1, size, data), ConvolveOp.EDGE_NO_OP, null);
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle dstBounds = new Rectangle(inputBounds);
|
||||
if (horizontal)
|
||||
{
|
||||
dstBounds.grow(size, 0);
|
||||
} else
|
||||
{
|
||||
dstBounds.grow(0, size);
|
||||
}
|
||||
|
||||
return new FilterOp(horizontal ? xBlur : yBlur, dstBounds);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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 March 18, 2004, 6:52 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
abstract public class FeLight extends FilterEffects
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "feLight";
|
||||
|
||||
/**
|
||||
* Creates a new instance of FillElement
|
||||
*/
|
||||
public FeLight()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* 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 March 18, 2004, 6:52 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class FePointLight extends FeLight
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "fepointlight";
|
||||
float x = 0f;
|
||||
float y = 0f;
|
||||
float z = 0f;
|
||||
|
||||
/**
|
||||
* Creates a new instance of FillElement
|
||||
*/
|
||||
public FePointLight()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
x = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
y = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("z")))
|
||||
{
|
||||
z = sty.getFloatValueWithUnits();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getX()
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getY()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
public float getZ()
|
||||
{
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean stateChange = false;
|
||||
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != x)
|
||||
{
|
||||
x = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != y)
|
||||
{
|
||||
y = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("z")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != z)
|
||||
{
|
||||
z = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
return stateChange;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* 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 March 18, 2004, 6:52 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class FeSpotLight extends FeLight
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "fespotlight";
|
||||
float x = 0f;
|
||||
float y = 0f;
|
||||
float z = 0f;
|
||||
float pointsAtX = 0f;
|
||||
float pointsAtY = 0f;
|
||||
float pointsAtZ = 0f;
|
||||
float specularComponent = 0f;
|
||||
float limitingConeAngle = 0f;
|
||||
|
||||
/**
|
||||
* Creates a new instance of FillElement
|
||||
*/
|
||||
public FeSpotLight()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
x = sty.getFloatValueWithUnits();
|
||||
}
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
y = sty.getFloatValueWithUnits();
|
||||
}
|
||||
if (getPres(sty.setName("z")))
|
||||
{
|
||||
z = sty.getFloatValueWithUnits();
|
||||
}
|
||||
if (getPres(sty.setName("pointsAtX")))
|
||||
{
|
||||
pointsAtX = sty.getFloatValueWithUnits();
|
||||
}
|
||||
if (getPres(sty.setName("pointsAtY")))
|
||||
{
|
||||
pointsAtY = sty.getFloatValueWithUnits();
|
||||
}
|
||||
if (getPres(sty.setName("pointsAtZ")))
|
||||
{
|
||||
pointsAtZ = sty.getFloatValueWithUnits();
|
||||
}
|
||||
if (getPres(sty.setName("specularComponent")))
|
||||
{
|
||||
specularComponent = sty.getFloatValueWithUnits();
|
||||
}
|
||||
if (getPres(sty.setName("limitingConeAngle")))
|
||||
{
|
||||
limitingConeAngle = sty.getFloatValueWithUnits();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getX()
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getY()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
public float getZ()
|
||||
{
|
||||
return z;
|
||||
}
|
||||
|
||||
public float getPointsAtX()
|
||||
{
|
||||
return pointsAtX;
|
||||
}
|
||||
|
||||
public float getPointsAtY()
|
||||
{
|
||||
return pointsAtY;
|
||||
}
|
||||
|
||||
public float getPointsAtZ()
|
||||
{
|
||||
return pointsAtZ;
|
||||
}
|
||||
|
||||
public float getSpecularComponent()
|
||||
{
|
||||
return specularComponent;
|
||||
}
|
||||
|
||||
public float getLimitingConeAngle()
|
||||
{
|
||||
return limitingConeAngle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean stateChange = false;
|
||||
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != x)
|
||||
{
|
||||
x = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != y)
|
||||
{
|
||||
y = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("z")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != z)
|
||||
{
|
||||
z = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("pointsAtX")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != pointsAtX)
|
||||
{
|
||||
pointsAtX = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("pointsAtY")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != pointsAtY)
|
||||
{
|
||||
pointsAtY = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("pointsAtZ")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != pointsAtZ)
|
||||
{
|
||||
pointsAtZ = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("specularComponent")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != specularComponent)
|
||||
{
|
||||
specularComponent = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("limitingConeAngle")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != limitingConeAngle)
|
||||
{
|
||||
limitingConeAngle = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
return stateChange;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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 March 18, 2004, 6:52 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.*;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
abstract public class FillElement extends SVGElement
|
||||
{
|
||||
/**
|
||||
* Creates a new instance of FillElement
|
||||
*/
|
||||
public FillElement()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the paint defined by this element. Passes in information to
|
||||
* allow paint to be customized
|
||||
*
|
||||
* @param bounds - bounding box of shape being rendered
|
||||
* @param xform - The current transformation that the shape is being
|
||||
* rendered under.
|
||||
* @return paint object
|
||||
*/
|
||||
abstract public Paint getPaint(Rectangle2D bounds, AffineTransform xform);
|
||||
}
|
287
graphics-svg/src/main/java/org/xbib/graphics/svg/Filter.java
Normal file
287
graphics-svg/src/main/java/org/xbib/graphics/svg/Filter.java
Normal file
|
@ -0,0 +1,287 @@
|
|||
/*
|
||||
* 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 March 18, 2004, 6:52 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Filter extends SVGElement
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "filter";
|
||||
public static final int FU_OBJECT_BOUNDING_BOX = 0;
|
||||
public static final int FU_USER_SPACE_ON_USE = 1;
|
||||
protected int filterUnits = FU_OBJECT_BOUNDING_BOX;
|
||||
public static final int PU_OBJECT_BOUNDING_BOX = 0;
|
||||
public static final int PU_USER_SPACE_ON_USE = 1;
|
||||
protected int primitiveUnits = PU_OBJECT_BOUNDING_BOX;
|
||||
float x = 0f;
|
||||
float y = 0f;
|
||||
float width = 1f;
|
||||
float height = 1f;
|
||||
Point2D filterRes = new Point2D.Double();
|
||||
URL href = null;
|
||||
final ArrayList<FilterEffects> filterEffects = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Creates a new instance of FillElement
|
||||
*/
|
||||
public Filter()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the start element but before the end element to indicate
|
||||
* each child tag that has been processed
|
||||
*/
|
||||
@Override
|
||||
public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
|
||||
{
|
||||
super.loaderAddChild(helper, child);
|
||||
|
||||
if (child instanceof FilterEffects)
|
||||
{
|
||||
filterEffects.add((FilterEffects) child);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
String strn;
|
||||
|
||||
if (getPres(sty.setName("filterUnits")))
|
||||
{
|
||||
strn = sty.getStringValue().toLowerCase();
|
||||
if (strn.equals("userspaceonuse"))
|
||||
{
|
||||
filterUnits = FU_USER_SPACE_ON_USE;
|
||||
} else
|
||||
{
|
||||
filterUnits = FU_OBJECT_BOUNDING_BOX;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("primitiveUnits")))
|
||||
{
|
||||
strn = sty.getStringValue().toLowerCase();
|
||||
if (strn.equals("userspaceonuse"))
|
||||
{
|
||||
primitiveUnits = PU_USER_SPACE_ON_USE;
|
||||
} else
|
||||
{
|
||||
primitiveUnits = PU_OBJECT_BOUNDING_BOX;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
x = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
y = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("width")))
|
||||
{
|
||||
width = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("height")))
|
||||
{
|
||||
height = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (getPres(sty.setName("xlink:href")))
|
||||
{
|
||||
URI src = sty.getURIValue(getXMLBase());
|
||||
href = src.toURL();
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
throw new SVGException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public float getX()
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
public float getY()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
public float getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
public float getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean stateChange = false;
|
||||
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != x)
|
||||
{
|
||||
x = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != y)
|
||||
{
|
||||
y = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("width")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != width)
|
||||
{
|
||||
width = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("height")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != height)
|
||||
{
|
||||
height = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (getPres(sty.setName("xlink:href")))
|
||||
{
|
||||
URI src = sty.getURIValue(getXMLBase());
|
||||
URL newVal = src.toURL();
|
||||
|
||||
if (!newVal.equals(href))
|
||||
{
|
||||
href = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
throw new SVGException(e);
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("filterUnits")))
|
||||
{
|
||||
int newVal;
|
||||
String strn = sty.getStringValue().toLowerCase();
|
||||
if (strn.equals("userspaceonuse"))
|
||||
{
|
||||
newVal = FU_USER_SPACE_ON_USE;
|
||||
} else
|
||||
{
|
||||
newVal = FU_OBJECT_BOUNDING_BOX;
|
||||
}
|
||||
if (newVal != filterUnits)
|
||||
{
|
||||
filterUnits = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("primitiveUnits")))
|
||||
{
|
||||
int newVal;
|
||||
String strn = sty.getStringValue().toLowerCase();
|
||||
if (strn.equals("userspaceonuse"))
|
||||
{
|
||||
newVal = PU_USER_SPACE_ON_USE;
|
||||
} else
|
||||
{
|
||||
newVal = PU_OBJECT_BOUNDING_BOX;
|
||||
}
|
||||
if (newVal != filterUnits)
|
||||
{
|
||||
primitiveUnits = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return stateChange;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
* 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 March 18, 2004, 6:52 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public abstract class FilterEffects extends SVGElement
|
||||
{
|
||||
public static final String TAG_NAME = "filtereffects";
|
||||
|
||||
public static final int FP_SOURCE_GRAPHIC = 0;
|
||||
public static final int FP_SOURCE_ALPHA = 1;
|
||||
public static final int FP_BACKGROUND_IMAGE = 2;
|
||||
public static final int FP_BACKGROUND_ALPHA = 3;
|
||||
public static final int FP_FILL_PAINT = 4;
|
||||
public static final int FP_STROKE_PAINT = 5;
|
||||
public static final int FP_CUSTOM = 5;
|
||||
private int filterPrimitiveTypeIn;
|
||||
private String filterPrimitiveRefIn;
|
||||
float x = 0f;
|
||||
float y = 0f;
|
||||
float width = 1f;
|
||||
float height = 1f;
|
||||
URL href = null;
|
||||
|
||||
/**
|
||||
* Creates a new instance of FillElement
|
||||
*/
|
||||
public FilterEffects()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the start element but before the end element to indicate
|
||||
* each child tag that has been processed
|
||||
*/
|
||||
@Override
|
||||
public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
|
||||
{
|
||||
super.loaderAddChild(helper, child);
|
||||
|
||||
if (child instanceof FilterEffects)
|
||||
{
|
||||
// filterEffects.add(child);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
/*StyleAttribute sty = new StyleAttribute();
|
||||
String strn;
|
||||
|
||||
if (getPres(sty.setName("filterUnits")))
|
||||
{
|
||||
strn = sty.getStringValue().toLowerCase();
|
||||
if (strn.equals("userspaceonuse")) filterUnits = FU_USER_SPACE_ON_USE;
|
||||
else filterUnits = FU_OBJECT_BOUNDING_BOX;
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("primitiveUnits")))
|
||||
{
|
||||
strn = sty.getStringValue().toLowerCase();
|
||||
if (strn.equals("userspaceonuse")) primitiveUnits = PU_USER_SPACE_ON_USE;
|
||||
else primitiveUnits = PU_OBJECT_BOUNDING_BOX;
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("x"))) x = sty.getFloatValue();
|
||||
|
||||
if (getPres(sty.setName("y"))) y = sty.getFloatValue();
|
||||
|
||||
if (getPres(sty.setName("width"))) width = sty.getFloatValue();
|
||||
|
||||
if (getPres(sty.setName("height"))) height = sty.getFloatValue();
|
||||
|
||||
try {
|
||||
if (getPres(sty.setName("xlink:href")))
|
||||
{
|
||||
URI src = sty.getURIValue(getXMLBase());
|
||||
href = src.toURL();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new SVGException(e);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public List<FilterOp> getOperations(Rectangle bounds, float xScale, float yScale) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public float getX()
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
public float getY()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
public float getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
public float getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean stateChange = false;
|
||||
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != x)
|
||||
{
|
||||
x = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != y)
|
||||
{
|
||||
y = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("width")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != width)
|
||||
{
|
||||
width = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("height")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != height)
|
||||
{
|
||||
height = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (getPres(sty.setName("xlink:href")))
|
||||
{
|
||||
URI src = sty.getURIValue(getXMLBase());
|
||||
URL newVal = src.toURL();
|
||||
|
||||
if (!newVal.equals(href))
|
||||
{
|
||||
href = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
throw new SVGException(e);
|
||||
}
|
||||
|
||||
/*
|
||||
if (getPres(sty.setName("filterUnits")))
|
||||
{
|
||||
int newVal;
|
||||
String strn = sty.getStringValue().toLowerCase();
|
||||
if (strn.equals("userspaceonuse")) newVal = FU_USER_SPACE_ON_USE;
|
||||
else newVal = FU_OBJECT_BOUNDING_BOX;
|
||||
if (newVal != filterUnits)
|
||||
{
|
||||
filterUnits = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("primitiveUnits")))
|
||||
{
|
||||
int newVal;
|
||||
String strn = sty.getStringValue().toLowerCase();
|
||||
if (strn.equals("userspaceonuse")) newVal = PU_USER_SPACE_ON_USE;
|
||||
else newVal = PU_OBJECT_BOUNDING_BOX;
|
||||
if (newVal != filterUnits)
|
||||
{
|
||||
primitiveUnits = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
return stateChange;
|
||||
}
|
||||
|
||||
public static class FilterOp {
|
||||
public final BufferedImageOp op;
|
||||
public final Rectangle requiredImageBounds;
|
||||
|
||||
public FilterOp(BufferedImageOp op, Rectangle requiredImageBounds) {
|
||||
this.op = op;
|
||||
this.requiredImageBounds = requiredImageBounds;
|
||||
}
|
||||
}
|
||||
}
|
292
graphics-svg/src/main/java/org/xbib/graphics/svg/Font.java
Normal file
292
graphics-svg/src/main/java/org/xbib/graphics/svg/Font.java
Normal file
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
* 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 20, 2004, 10:00 PM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Implements an embedded font.
|
||||
*
|
||||
* SVG specification: http://www.w3.org/TR/SVG/fonts.html
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Font extends SVGElement
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "font";
|
||||
int horizOriginX = 0;
|
||||
int horizOriginY = 0;
|
||||
int horizAdvX = -1; //Must be specified
|
||||
int vertOriginX = -1; //Defaults to horizAdvX / 2
|
||||
int vertOriginY = -1; //Defaults to font's ascent
|
||||
int vertAdvY = -1; //Defaults to one 'em'. See font-face
|
||||
FontFace fontFace = null;
|
||||
MissingGlyph missingGlyph = null;
|
||||
final HashMap<String, SVGElement> glyphs = new HashMap<String, SVGElement>();
|
||||
|
||||
/**
|
||||
* Creates a new instance of Font
|
||||
*/
|
||||
public Font()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the start element but before the end element to indicate
|
||||
* each child tag that has been processed
|
||||
*/
|
||||
@Override
|
||||
public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
|
||||
{
|
||||
super.loaderAddChild(helper, child);
|
||||
|
||||
if (child instanceof Glyph)
|
||||
{
|
||||
glyphs.put(((Glyph) child).getUnicode(), child);
|
||||
} else if (child instanceof MissingGlyph)
|
||||
{
|
||||
missingGlyph = (MissingGlyph) child;
|
||||
} else if (child instanceof FontFace)
|
||||
{
|
||||
fontFace = (FontFace) child;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loaderEndElement(SVGLoaderHelper helper) throws SVGParseException
|
||||
{
|
||||
super.loaderEndElement(helper);
|
||||
|
||||
//build();
|
||||
|
||||
helper.universe.registerFont(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("horiz-origin-x")))
|
||||
{
|
||||
horizOriginX = sty.getIntValue();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("horiz-origin-y")))
|
||||
{
|
||||
horizOriginY = sty.getIntValue();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("horiz-adv-x")))
|
||||
{
|
||||
horizAdvX = sty.getIntValue();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("vert-origin-x")))
|
||||
{
|
||||
vertOriginX = sty.getIntValue();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("vert-origin-y")))
|
||||
{
|
||||
vertOriginY = sty.getIntValue();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("vert-adv-y")))
|
||||
{
|
||||
vertAdvY = sty.getIntValue();
|
||||
}
|
||||
}
|
||||
|
||||
public FontFace getFontFace()
|
||||
{
|
||||
return fontFace;
|
||||
}
|
||||
|
||||
public void setFontFace(FontFace face)
|
||||
{
|
||||
fontFace = face;
|
||||
}
|
||||
|
||||
public MissingGlyph getGlyph(String unicode)
|
||||
{
|
||||
Glyph retVal = (Glyph) glyphs.get(unicode);
|
||||
if (retVal == null)
|
||||
{
|
||||
return missingGlyph;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public int getHorizOriginX()
|
||||
{
|
||||
return horizOriginX;
|
||||
}
|
||||
|
||||
public int getHorizOriginY()
|
||||
{
|
||||
return horizOriginY;
|
||||
}
|
||||
|
||||
public int getHorizAdvX()
|
||||
{
|
||||
return horizAdvX;
|
||||
}
|
||||
|
||||
public int getVertOriginX()
|
||||
{
|
||||
if (vertOriginX != -1)
|
||||
{
|
||||
return vertOriginX;
|
||||
}
|
||||
vertOriginX = getHorizAdvX() / 2;
|
||||
return vertOriginX;
|
||||
}
|
||||
|
||||
public int getVertOriginY()
|
||||
{
|
||||
if (vertOriginY != -1)
|
||||
{
|
||||
return vertOriginY;
|
||||
}
|
||||
vertOriginY = fontFace.getAscent();
|
||||
return vertOriginY;
|
||||
}
|
||||
|
||||
public int getVertAdvY()
|
||||
{
|
||||
if (vertAdvY != -1)
|
||||
{
|
||||
return vertAdvY;
|
||||
}
|
||||
vertAdvY = fontFace.getUnitsPerEm();
|
||||
return vertAdvY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
//Fonts can't change
|
||||
return false;
|
||||
/*
|
||||
if (trackManager.getNumTracks() == 0) return false;
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean stateChange = false;
|
||||
|
||||
if (getPres(sty.setName("horiz-origin-x")))
|
||||
{
|
||||
int newVal = sty.getIntValue();
|
||||
if (newVal != horizOriginX)
|
||||
{
|
||||
horizOriginX = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("horiz-origin-y")))
|
||||
{
|
||||
int newVal = sty.getIntValue();
|
||||
if (newVal != horizOriginY)
|
||||
{
|
||||
horizOriginY = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("horiz-adv-x")))
|
||||
{
|
||||
int newVal = sty.getIntValue();
|
||||
if (newVal != horizAdvX)
|
||||
{
|
||||
horizAdvX = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("vert-origin-x")))
|
||||
{
|
||||
int newVal = sty.getIntValue();
|
||||
if (newVal != vertOriginX)
|
||||
{
|
||||
vertOriginX = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("vert-origin-y")))
|
||||
{
|
||||
int newVal = sty.getIntValue();
|
||||
if (newVal != vertOriginY)
|
||||
{
|
||||
vertOriginY = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("vert-adv-y")))
|
||||
{
|
||||
int newVal = sty.getIntValue();
|
||||
if (newVal != vertAdvY)
|
||||
{
|
||||
vertAdvY = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
return shapeChange;
|
||||
*/
|
||||
}
|
||||
}
|
319
graphics-svg/src/main/java/org/xbib/graphics/svg/FontFace.java
Normal file
319
graphics-svg/src/main/java/org/xbib/graphics/svg/FontFace.java
Normal file
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
* 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 20, 2004, 10:00 PM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
|
||||
/**
|
||||
* Implements an embedded font.
|
||||
*
|
||||
* SVG specification: http://www.w3.org/TR/SVG/fonts.html
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class FontFace extends SVGElement
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "fontface";
|
||||
String fontFamily;
|
||||
/**
|
||||
* Em size of coordinate system font is defined in
|
||||
*/
|
||||
private int unitsPerEm = 1000;
|
||||
private int ascent = -1;
|
||||
private int descent = -1;
|
||||
private int accentHeight = -1;
|
||||
private int underlinePosition = -1;
|
||||
private int underlineThickness = -1;
|
||||
private int strikethroughPosition = -1;
|
||||
private int strikethroughThickness = -1;
|
||||
private int overlinePosition = -1;
|
||||
private int overlineThickness = -1;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Font
|
||||
*/
|
||||
public FontFace()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("font-family")))
|
||||
{
|
||||
fontFamily = sty.getStringValue();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("units-per-em")))
|
||||
{
|
||||
unitsPerEm = sty.getIntValue();
|
||||
}
|
||||
if (getPres(sty.setName("ascent")))
|
||||
{
|
||||
ascent = sty.getIntValue();
|
||||
}
|
||||
if (getPres(sty.setName("descent")))
|
||||
{
|
||||
descent = sty.getIntValue();
|
||||
}
|
||||
if (getPres(sty.setName("accent-height")))
|
||||
{
|
||||
accentHeight = sty.getIntValue();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("underline-position")))
|
||||
{
|
||||
underlinePosition = sty.getIntValue();
|
||||
}
|
||||
if (getPres(sty.setName("underline-thickness")))
|
||||
{
|
||||
underlineThickness = sty.getIntValue();
|
||||
}
|
||||
if (getPres(sty.setName("strikethrough-position")))
|
||||
{
|
||||
strikethroughPosition = sty.getIntValue();
|
||||
}
|
||||
if (getPres(sty.setName("strikethrough-thickenss")))
|
||||
{
|
||||
strikethroughThickness = sty.getIntValue();
|
||||
}
|
||||
if (getPres(sty.setName("overline-position")))
|
||||
{
|
||||
overlinePosition = sty.getIntValue();
|
||||
}
|
||||
if (getPres(sty.setName("overline-thickness")))
|
||||
{
|
||||
overlineThickness = sty.getIntValue();
|
||||
}
|
||||
}
|
||||
|
||||
public String getFontFamily()
|
||||
{
|
||||
return fontFamily;
|
||||
}
|
||||
|
||||
public int getUnitsPerEm()
|
||||
{
|
||||
return unitsPerEm;
|
||||
}
|
||||
|
||||
public int getAscent()
|
||||
{
|
||||
if (ascent == -1)
|
||||
{
|
||||
ascent = unitsPerEm - ((Font) parent).getVertOriginY();
|
||||
}
|
||||
return ascent;
|
||||
}
|
||||
|
||||
public int getDescent()
|
||||
{
|
||||
if (descent == -1)
|
||||
{
|
||||
descent = ((Font) parent).getVertOriginY();
|
||||
}
|
||||
return descent;
|
||||
}
|
||||
|
||||
public int getAccentHeight()
|
||||
{
|
||||
if (accentHeight == -1)
|
||||
{
|
||||
accentHeight = getAscent();
|
||||
}
|
||||
return accentHeight;
|
||||
}
|
||||
|
||||
public int getUnderlinePosition()
|
||||
{
|
||||
if (underlinePosition == -1)
|
||||
{
|
||||
underlinePosition = unitsPerEm * 5 / 6;
|
||||
}
|
||||
return underlinePosition;
|
||||
}
|
||||
|
||||
public int getUnderlineThickness()
|
||||
{
|
||||
if (underlineThickness == -1)
|
||||
{
|
||||
underlineThickness = unitsPerEm / 20;
|
||||
}
|
||||
return underlineThickness;
|
||||
}
|
||||
|
||||
public int getStrikethroughPosition()
|
||||
{
|
||||
if (strikethroughPosition == -1)
|
||||
{
|
||||
strikethroughPosition = unitsPerEm * 3 / 6;
|
||||
}
|
||||
return strikethroughPosition;
|
||||
}
|
||||
|
||||
public int getStrikethroughThickness()
|
||||
{
|
||||
if (strikethroughThickness == -1)
|
||||
{
|
||||
strikethroughThickness = unitsPerEm / 20;
|
||||
}
|
||||
return strikethroughThickness;
|
||||
}
|
||||
|
||||
public int getOverlinePosition()
|
||||
{
|
||||
if (overlinePosition == -1)
|
||||
{
|
||||
overlinePosition = unitsPerEm * 5 / 6;
|
||||
}
|
||||
return overlinePosition;
|
||||
}
|
||||
|
||||
public int getOverlineThickness()
|
||||
{
|
||||
if (overlineThickness == -1)
|
||||
{
|
||||
overlineThickness = unitsPerEm / 20;
|
||||
}
|
||||
return overlineThickness;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime)
|
||||
{
|
||||
//Fonts can't change
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param unitsPerEm the unitsPerEm to set
|
||||
*/
|
||||
public void setUnitsPerEm(int unitsPerEm)
|
||||
{
|
||||
this.unitsPerEm = unitsPerEm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ascent the ascent to set
|
||||
*/
|
||||
public void setAscent(int ascent)
|
||||
{
|
||||
this.ascent = ascent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param descent the descent to set
|
||||
*/
|
||||
public void setDescent(int descent)
|
||||
{
|
||||
this.descent = descent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param accentHeight the accentHeight to set
|
||||
*/
|
||||
public void setAccentHeight(int accentHeight)
|
||||
{
|
||||
this.accentHeight = accentHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param underlinePosition the underlinePosition to set
|
||||
*/
|
||||
public void setUnderlinePosition(int underlinePosition)
|
||||
{
|
||||
this.underlinePosition = underlinePosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param underlineThickness the underlineThickness to set
|
||||
*/
|
||||
public void setUnderlineThickness(int underlineThickness)
|
||||
{
|
||||
this.underlineThickness = underlineThickness;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param strikethroughPosition the strikethroughPosition to set
|
||||
*/
|
||||
public void setStrikethroughPosition(int strikethroughPosition)
|
||||
{
|
||||
this.strikethroughPosition = strikethroughPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param strikethroughThickness the strikethroughThickness to set
|
||||
*/
|
||||
public void setStrikethroughThickness(int strikethroughThickness)
|
||||
{
|
||||
this.strikethroughThickness = strikethroughThickness;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param overlinePosition the overlinePosition to set
|
||||
*/
|
||||
public void setOverlinePosition(int overlinePosition)
|
||||
{
|
||||
this.overlinePosition = overlinePosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param overlineThickness the overlineThickness to set
|
||||
*/
|
||||
public void setOverlineThickness(int overlineThickness)
|
||||
{
|
||||
this.overlineThickness = overlineThickness;
|
||||
}
|
||||
}
|
102
graphics-svg/src/main/java/org/xbib/graphics/svg/Glyph.java
Normal file
102
graphics-svg/src/main/java/org/xbib/graphics/svg/Glyph.java
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* 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 20, 2004, 10:00 PM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
|
||||
/**
|
||||
* Implements an embedded font.
|
||||
*
|
||||
* SVG specification: http://www.w3.org/TR/SVG/fonts.html
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Glyph extends MissingGlyph
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "missingglyph";
|
||||
/**
|
||||
* One or more characters indicating the unicode sequence that denotes this
|
||||
* glyph.
|
||||
*/
|
||||
String unicode;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Font
|
||||
*/
|
||||
public Glyph()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("unicode")))
|
||||
{
|
||||
unicode = sty.getStringValue();
|
||||
}
|
||||
}
|
||||
|
||||
public String getUnicode()
|
||||
{
|
||||
return unicode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
//Fonts can't change
|
||||
return false;
|
||||
}
|
||||
}
|
367
graphics-svg/src/main/java/org/xbib/graphics/svg/Gradient.java
Normal file
367
graphics-svg/src/main/java/org/xbib/graphics/svg/Gradient.java
Normal file
|
@ -0,0 +1,367 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 3:25 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Color;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
abstract public class Gradient extends FillElement
|
||||
{
|
||||
public static final String TAG_NAME = "gradient";
|
||||
|
||||
public static final int SM_PAD = 0;
|
||||
public static final int SM_REPEAT = 1;
|
||||
public static final int SM_REFLECT = 2;
|
||||
int spreadMethod = SM_PAD;
|
||||
public static final int GU_OBJECT_BOUNDING_BOX = 0;
|
||||
public static final int GU_USER_SPACE_ON_USE = 1;
|
||||
protected int gradientUnits = GU_OBJECT_BOUNDING_BOX;
|
||||
//Either this gradient contains a list of stops, or it will take it's
|
||||
// stops from the referenced gradient
|
||||
ArrayList<Stop> stops = new ArrayList<Stop>();
|
||||
URI stopRef = null;
|
||||
protected AffineTransform gradientTransform = null;
|
||||
|
||||
//Cache arrays of stop values here
|
||||
float[] stopFractions;
|
||||
Color[] stopColors;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Gradient
|
||||
*/
|
||||
public Gradient()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the start element but before the end element to indicate
|
||||
* each child tag that has been processed
|
||||
*/
|
||||
@Override
|
||||
public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
|
||||
{
|
||||
super.loaderAddChild(helper, child);
|
||||
|
||||
if (!(child instanceof Stop))
|
||||
{
|
||||
return;
|
||||
}
|
||||
appendStop((Stop) child);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
String strn;
|
||||
|
||||
if (getPres(sty.setName("spreadMethod")))
|
||||
{
|
||||
strn = sty.getStringValue().toLowerCase();
|
||||
if (strn.equals("repeat"))
|
||||
{
|
||||
spreadMethod = SM_REPEAT;
|
||||
} else if (strn.equals("reflect"))
|
||||
{
|
||||
spreadMethod = SM_REFLECT;
|
||||
} else
|
||||
{
|
||||
spreadMethod = SM_PAD;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("gradientUnits")))
|
||||
{
|
||||
strn = sty.getStringValue().toLowerCase();
|
||||
if (strn.equals("userspaceonuse"))
|
||||
{
|
||||
gradientUnits = GU_USER_SPACE_ON_USE;
|
||||
} else
|
||||
{
|
||||
gradientUnits = GU_OBJECT_BOUNDING_BOX;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("gradientTransform")))
|
||||
{
|
||||
gradientTransform = parseTransform(sty.getStringValue());
|
||||
}
|
||||
//If we still don't have one, set it to identity
|
||||
if (gradientTransform == null)
|
||||
{
|
||||
gradientTransform = new AffineTransform();
|
||||
}
|
||||
|
||||
|
||||
//Check to see if we're using our own stops or referencing someone else's
|
||||
if (getPres(sty.setName("xlink:href")))
|
||||
{
|
||||
try
|
||||
{
|
||||
stopRef = sty.getURIValue(getXMLBase());
|
||||
//System.err.println("Gradient: " + sty.getStringValue() + ", " + getXMLBase() + ", " + src);
|
||||
// URI src = getXMLBase().resolve(href);
|
||||
// stopRef = (Gradient)diagram.getUniverse().getElement(src);
|
||||
} catch (Exception e)
|
||||
{
|
||||
throw new SVGException("Could not resolve relative URL in Gradient: " + sty.getStringValue() + ", " + getXMLBase(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void buildStops()
|
||||
{
|
||||
ArrayList<Stop> stopList = new ArrayList<Stop>(stops);
|
||||
stopList.sort(new Comparator<Stop>(){
|
||||
public int compare(Stop o1, Stop o2)
|
||||
{
|
||||
return Float.compare(o1.offset, o2.offset);
|
||||
}
|
||||
});
|
||||
|
||||
//Remove doubles
|
||||
for (int i = stopList.size() - 2; i >= 0; --i)
|
||||
{
|
||||
if (stopList.get(i + 1).offset == stopList.get(i).offset)
|
||||
{
|
||||
stopList.remove(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
stopFractions = new float[stopList.size()];
|
||||
stopColors = new Color[stopList.size()];
|
||||
int idx = 0;
|
||||
for (Stop stop : stopList)
|
||||
{
|
||||
int stopColorVal = stop.color.getRGB();
|
||||
Color stopColor = new Color((stopColorVal >> 16) & 0xff, (stopColorVal >> 8) & 0xff, stopColorVal & 0xff, clamp((int) (stop.opacity * 255), 0, 255));
|
||||
|
||||
stopColors[idx] = stopColor;
|
||||
stopFractions[idx] = stop.offset;
|
||||
idx++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public float[] getStopFractions()
|
||||
{
|
||||
if (stopRef != null)
|
||||
{
|
||||
Gradient grad = (Gradient) diagram.getUniverse().getElement(stopRef);
|
||||
return grad.getStopFractions();
|
||||
}
|
||||
|
||||
if (stopFractions != null)
|
||||
{
|
||||
return stopFractions;
|
||||
}
|
||||
|
||||
buildStops();
|
||||
|
||||
return stopFractions;
|
||||
}
|
||||
|
||||
public Color[] getStopColors()
|
||||
{
|
||||
if (stopRef != null)
|
||||
{
|
||||
Gradient grad = (Gradient) diagram.getUniverse().getElement(stopRef);
|
||||
return grad.getStopColors();
|
||||
}
|
||||
|
||||
if (stopColors != null)
|
||||
{
|
||||
return stopColors;
|
||||
}
|
||||
|
||||
buildStops();
|
||||
|
||||
return stopColors;
|
||||
}
|
||||
|
||||
// public void setStops(Color[] colors, float[] fractions)
|
||||
// {
|
||||
// if (colors.length != fractions.length)
|
||||
// {
|
||||
// throw new IllegalArgumentException();
|
||||
// }
|
||||
//
|
||||
// this.stopColors = colors;
|
||||
// this.stopFractions = fractions;
|
||||
// stopRef = null;
|
||||
// }
|
||||
|
||||
private int clamp(int val, int min, int max)
|
||||
{
|
||||
if (val < min)
|
||||
{
|
||||
return min;
|
||||
}
|
||||
if (val > max)
|
||||
{
|
||||
return max;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public void setStopRef(URI grad)
|
||||
{
|
||||
stopRef = grad;
|
||||
}
|
||||
|
||||
public void appendStop(Stop stop)
|
||||
{
|
||||
stops.add(stop);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
boolean stateChange = false;
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
String strn;
|
||||
|
||||
|
||||
if (getPres(sty.setName("spreadMethod")))
|
||||
{
|
||||
int newVal;
|
||||
strn = sty.getStringValue().toLowerCase();
|
||||
if (strn.equals("repeat"))
|
||||
{
|
||||
newVal = SM_REPEAT;
|
||||
} else if (strn.equals("reflect"))
|
||||
{
|
||||
newVal = SM_REFLECT;
|
||||
} else
|
||||
{
|
||||
newVal = SM_PAD;
|
||||
}
|
||||
if (spreadMethod != newVal)
|
||||
{
|
||||
spreadMethod = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("gradientUnits")))
|
||||
{
|
||||
int newVal;
|
||||
strn = sty.getStringValue().toLowerCase();
|
||||
if (strn.equals("userspaceonuse"))
|
||||
{
|
||||
newVal = GU_USER_SPACE_ON_USE;
|
||||
} else
|
||||
{
|
||||
newVal = GU_OBJECT_BOUNDING_BOX;
|
||||
}
|
||||
if (newVal != gradientUnits)
|
||||
{
|
||||
gradientUnits = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("gradientTransform")))
|
||||
{
|
||||
AffineTransform newVal = parseTransform(sty.getStringValue());
|
||||
if (newVal != null && newVal.equals(gradientTransform))
|
||||
{
|
||||
gradientTransform = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Check to see if we're using our own stops or referencing someone else's
|
||||
if (getPres(sty.setName("xlink:href")))
|
||||
{
|
||||
try
|
||||
{
|
||||
URI newVal = sty.getURIValue(getXMLBase());
|
||||
if ((newVal == null && stopRef != null) || !newVal.equals(stopRef))
|
||||
{
|
||||
stopRef = newVal;
|
||||
stateChange = true;
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not parse xlink:href", e);
|
||||
}
|
||||
}
|
||||
|
||||
//Check stops, if any
|
||||
for (Stop stop : stops) {
|
||||
if (stop.updateTime(curTime))
|
||||
{
|
||||
stateChange = true;
|
||||
stopFractions = null;
|
||||
stopColors = null;
|
||||
}
|
||||
}
|
||||
|
||||
return stateChange;
|
||||
}
|
||||
}
|
340
graphics-svg/src/main/java/org/xbib/graphics/svg/Group.java
Normal file
340
graphics-svg/src/main/java/org/xbib/graphics/svg/Group.java
Normal file
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 1:56 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.NoninvertibleTransformException;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Group extends ShapeElement
|
||||
{
|
||||
public static final String TAG_NAME = "group";
|
||||
|
||||
//Cache bounding box for faster clip testing
|
||||
Rectangle2D boundingBox;
|
||||
Shape cachedShape;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Stop
|
||||
*/
|
||||
public Group()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the start element but before the end element to indicate
|
||||
* each child tag that has been processed
|
||||
*/
|
||||
@Override
|
||||
public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
|
||||
{
|
||||
super.loaderAddChild(helper, child);
|
||||
}
|
||||
|
||||
protected boolean outsideClip(Graphics2D g) throws SVGException
|
||||
{
|
||||
Shape clip = g.getClip();
|
||||
if (clip == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//g.getClipBounds(clipBounds);
|
||||
Rectangle2D rect = getBoundingBox();
|
||||
|
||||
if (clip.intersects(rect))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPick(Point2D point, boolean boundingBox, List<List<SVGElement>> retVec) throws SVGException
|
||||
{
|
||||
Point2D xPoint = new Point2D.Double(point.getX(), point.getY());
|
||||
if (xform != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
xform.inverseTransform(point, xPoint);
|
||||
} catch (NoninvertibleTransformException ex)
|
||||
{
|
||||
throw new SVGException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (SVGElement ele : children) {
|
||||
if (ele instanceof RenderableElement)
|
||||
{
|
||||
RenderableElement rendEle = (RenderableElement) ele;
|
||||
|
||||
rendEle.pick(xPoint, boundingBox, retVec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPick(Rectangle2D pickArea, AffineTransform ltw, boolean boundingBox, List<List<SVGElement>> retVec) throws SVGException
|
||||
{
|
||||
if (xform != null)
|
||||
{
|
||||
ltw = new AffineTransform(ltw);
|
||||
ltw.concatenate(xform);
|
||||
}
|
||||
|
||||
|
||||
for (SVGElement ele : children) {
|
||||
if (ele instanceof RenderableElement)
|
||||
{
|
||||
RenderableElement rendEle = (RenderableElement) ele;
|
||||
|
||||
rendEle.pick(pickArea, ltw, boundingBox, retVec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRender(Graphics2D g) throws SVGException
|
||||
{
|
||||
//Don't process if not visible
|
||||
StyleAttribute styleAttrib = new StyleAttribute();
|
||||
//Visibility can be overridden by children
|
||||
|
||||
if (getStyle(styleAttrib.setName("display")))
|
||||
{
|
||||
if (styleAttrib.getStringValue().equals("none"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Do not process offscreen groups
|
||||
boolean ignoreClip = diagram.ignoringClipHeuristic();
|
||||
// if (!ignoreClip && outsideClip(g))
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
|
||||
beginLayer(g);
|
||||
|
||||
Iterator<SVGElement> it = children.iterator();
|
||||
|
||||
// try
|
||||
// {
|
||||
// g.getClipBounds(clipBounds);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// //For some reason, getClipBounds can throw a null pointer exception for
|
||||
// // some types of Graphics2D
|
||||
// ignoreClip = true;
|
||||
// }
|
||||
|
||||
Shape clip = g.getClip();
|
||||
while (it.hasNext())
|
||||
{
|
||||
SVGElement ele = it.next();
|
||||
if (ele instanceof RenderableElement)
|
||||
{
|
||||
RenderableElement rendEle = (RenderableElement) ele;
|
||||
|
||||
// if (shapeEle == null) continue;
|
||||
|
||||
if (!(ele instanceof Group))
|
||||
{
|
||||
//Skip if clipping area is outside our bounds
|
||||
if (!ignoreClip && clip != null
|
||||
&& !clip.intersects(rendEle.getBoundingBox()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
rendEle.render(g);
|
||||
}
|
||||
}
|
||||
|
||||
finishLayer(g);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the cached bounding box of this group
|
||||
*/
|
||||
@Override
|
||||
public Shape getShape()
|
||||
{
|
||||
if (cachedShape == null)
|
||||
{
|
||||
calcShape();
|
||||
}
|
||||
return cachedShape;
|
||||
}
|
||||
|
||||
public void calcShape()
|
||||
{
|
||||
Area retShape = new Area();
|
||||
|
||||
for (SVGElement ele : children) {
|
||||
if (ele instanceof ShapeElement)
|
||||
{
|
||||
ShapeElement shpEle = (ShapeElement) ele;
|
||||
Shape shape = shpEle.getShape();
|
||||
if (shape != null)
|
||||
{
|
||||
retShape.add(new Area(shape));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cachedShape = shapeToParent(retShape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the cached bounding box of this group
|
||||
*/
|
||||
@Override
|
||||
public Rectangle2D getBoundingBox() throws SVGException
|
||||
{
|
||||
if (boundingBox == null)
|
||||
{
|
||||
calcBoundingBox();
|
||||
}
|
||||
// calcBoundingBox();
|
||||
return boundingBox;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculates the bounding box by taking the union of the bounding boxes
|
||||
* of all children. Caches the result.
|
||||
* @throws SVGException
|
||||
*/
|
||||
public void calcBoundingBox() throws SVGException
|
||||
{
|
||||
Rectangle2D retRect = null;
|
||||
|
||||
for (SVGElement ele : children) {
|
||||
if (ele instanceof RenderableElement)
|
||||
{
|
||||
RenderableElement rendEle = (RenderableElement) ele;
|
||||
Rectangle2D bounds = rendEle.getBoundingBox();
|
||||
if (bounds != null && (bounds.getWidth() != 0 || bounds.getHeight() != 0))
|
||||
{
|
||||
if (retRect == null)
|
||||
{
|
||||
retRect = bounds;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (retRect.getWidth() != 0 || retRect.getHeight() != 0)
|
||||
{
|
||||
retRect = retRect.createUnion(bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if (xform != null)
|
||||
// {
|
||||
// retRect = xform.createTransformedShape(retRect).getBounds2D();
|
||||
// }
|
||||
|
||||
//If no contents, use degenerate rectangle
|
||||
if (retRect == null)
|
||||
{
|
||||
retRect = new Rectangle2D.Float();
|
||||
}
|
||||
|
||||
boundingBox = boundsToParent(retRect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
Iterator<SVGElement> it = children.iterator();
|
||||
|
||||
//Distribute message to all members of this group
|
||||
while (it.hasNext())
|
||||
{
|
||||
SVGElement ele = it.next();
|
||||
boolean updateVal = ele.updateTime(curTime);
|
||||
|
||||
if (updateVal && ele instanceof RenderableElement)
|
||||
{
|
||||
((RenderableElement) ele).setBufferImage(null);
|
||||
}
|
||||
|
||||
changeState = changeState || updateVal;
|
||||
|
||||
//Update our shape if shape aware children change
|
||||
if (ele instanceof ShapeElement)
|
||||
{
|
||||
cachedShape = null;
|
||||
}
|
||||
if (ele instanceof RenderableElement)
|
||||
{
|
||||
boundingBox = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (changeState)
|
||||
{
|
||||
setBufferImage(null);
|
||||
}
|
||||
|
||||
return changeState;
|
||||
}
|
||||
}
|
89
graphics-svg/src/main/java/org/xbib/graphics/svg/Hkern.java
Normal file
89
graphics-svg/src/main/java/org/xbib/graphics/svg/Hkern.java
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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 20, 2004, 10:00 PM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class Hkern extends SVGElement
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "hkern";
|
||||
String u1;
|
||||
String u2;
|
||||
int k;
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
|
||||
//Read glyph spacing info
|
||||
if (getPres(sty.setName("u1")))
|
||||
{
|
||||
u1 = sty.getStringValue();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("u2")))
|
||||
{
|
||||
u2 = sty.getStringValue();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("k")))
|
||||
{
|
||||
k = sty.getIntValue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
//Fonts can't change
|
||||
return false;
|
||||
}
|
||||
}
|
398
graphics-svg/src/main/java/org/xbib/graphics/svg/ImageSVG.java
Normal file
398
graphics-svg/src/main/java/org/xbib/graphics/svg/ImageSVG.java
Normal file
|
@ -0,0 +1,398 @@
|
|||
/*
|
||||
* 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 20, 2004, 10:00 PM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.app.data.Handler;
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Implements an image.
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class ImageSVG extends RenderableElement
|
||||
{
|
||||
public static final String TAG_NAME = "image";
|
||||
|
||||
float x = 0f;
|
||||
float y = 0f;
|
||||
float width = 0f;
|
||||
float height = 0f;
|
||||
// BufferedImage href = null;
|
||||
URL imageSrc = null;
|
||||
AffineTransform xform;
|
||||
Rectangle2D bounds;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Font
|
||||
*/
|
||||
public ImageSVG()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
x = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
y = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("width")))
|
||||
{
|
||||
width = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("height")))
|
||||
{
|
||||
height = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (getPres(sty.setName("xlink:href")))
|
||||
{
|
||||
URI src = sty.getURIValue(getXMLBase());
|
||||
if ("data".equals(src.getScheme()))
|
||||
{
|
||||
imageSrc = new URL(null, src.toASCIIString(), new Handler());
|
||||
}
|
||||
else if (!diagram.getUniverse().isImageDataInlineOnly())
|
||||
{
|
||||
try
|
||||
{
|
||||
imageSrc = src.toURL();
|
||||
} catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not parse xlink:href " + src, e);
|
||||
imageSrc = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
throw new SVGException(e);
|
||||
}
|
||||
|
||||
if (imageSrc != null)
|
||||
{
|
||||
diagram.getUniverse().registerImage(imageSrc);
|
||||
|
||||
//Set widths if not set
|
||||
BufferedImage img = diagram.getUniverse().getImage(imageSrc);
|
||||
if (img == null)
|
||||
{
|
||||
xform = new AffineTransform();
|
||||
bounds = new Rectangle2D.Float();
|
||||
return;
|
||||
}
|
||||
|
||||
if (width == 0)
|
||||
{
|
||||
width = img.getWidth();
|
||||
}
|
||||
if (height == 0)
|
||||
{
|
||||
height = img.getHeight();
|
||||
}
|
||||
|
||||
//Determine image xform
|
||||
xform = new AffineTransform();
|
||||
xform.translate(this.x, this.y);
|
||||
xform.scale(this.width / img.getWidth(), this.height / img.getHeight());
|
||||
}
|
||||
|
||||
bounds = new Rectangle2D.Float(this.x, this.y, this.width, this.height);
|
||||
}
|
||||
|
||||
public float getX()
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
public float getY()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
public float getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
public float getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPick(Point2D point, boolean boundingBox, List<List<SVGElement>> retVec) throws SVGException
|
||||
{
|
||||
if (getBoundingBox().contains(point))
|
||||
{
|
||||
retVec.add(getPath(null));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPick(Rectangle2D pickArea, AffineTransform ltw, boolean boundingBox, List<List<SVGElement>> retVec) throws SVGException
|
||||
{
|
||||
if (ltw.createTransformedShape(getBoundingBox()).intersects(pickArea))
|
||||
{
|
||||
retVec.add(getPath(null));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRender(Graphics2D g) throws SVGException
|
||||
{
|
||||
StyleAttribute styleAttrib = new StyleAttribute();
|
||||
if (getStyle(styleAttrib.setName("visibility")))
|
||||
{
|
||||
if (!styleAttrib.getStringValue().equals("visible"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (getStyle(styleAttrib.setName("display")))
|
||||
{
|
||||
if (styleAttrib.getStringValue().equals("none"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
beginLayer(g);
|
||||
|
||||
float opacity = 1f;
|
||||
if (getStyle(styleAttrib.setName("opacity")))
|
||||
{
|
||||
opacity = styleAttrib.getRatioValue();
|
||||
}
|
||||
|
||||
if (opacity <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Composite oldComp = null;
|
||||
|
||||
if (opacity < 1)
|
||||
{
|
||||
oldComp = g.getComposite();
|
||||
Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity);
|
||||
g.setComposite(comp);
|
||||
}
|
||||
|
||||
BufferedImage img = diagram.getUniverse().getImage(imageSrc);
|
||||
if (img == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AffineTransform curXform = g.getTransform();
|
||||
g.transform(xform);
|
||||
|
||||
g.drawImage(img, 0, 0, diagram.getCurrentRenderTarget());
|
||||
|
||||
g.setTransform(curXform);
|
||||
if (oldComp != null)
|
||||
{
|
||||
g.setComposite(oldComp);
|
||||
}
|
||||
|
||||
finishLayer(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBoundingBox()
|
||||
{
|
||||
return boundsToParent(bounds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean shapeChange = false;
|
||||
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != x)
|
||||
{
|
||||
x = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != y)
|
||||
{
|
||||
y = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("width")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != width)
|
||||
{
|
||||
width = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("height")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != height)
|
||||
{
|
||||
height = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (getPres(sty.setName("xlink:href")))
|
||||
{
|
||||
URI src = sty.getURIValue(getXMLBase());
|
||||
|
||||
URL newVal = null;
|
||||
if ("data".equals(src.getScheme()))
|
||||
{
|
||||
newVal = new URL(null, src.toASCIIString(), new Handler());
|
||||
} else if (!diagram.getUniverse().isImageDataInlineOnly())
|
||||
{
|
||||
newVal = src.toURL();
|
||||
}
|
||||
|
||||
if (newVal != null && !newVal.equals(imageSrc))
|
||||
{
|
||||
imageSrc = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
} catch (IllegalArgumentException ie)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Image provided with illegal value for href: \""
|
||||
+ sty.getStringValue() + '"', ie);
|
||||
} catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not parse xlink:href", e);
|
||||
}
|
||||
|
||||
|
||||
if (shapeChange)
|
||||
{
|
||||
build();
|
||||
// diagram.getUniverse().registerImage(imageSrc);
|
||||
//
|
||||
// //Set widths if not set
|
||||
// BufferedImage img = diagram.getUniverse().getImage(imageSrc);
|
||||
// if (img == null)
|
||||
// {
|
||||
// xform = new AffineTransform();
|
||||
// bounds = new Rectangle2D.Float();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (width == 0) width = img.getWidth();
|
||||
// if (height == 0) height = img.getHeight();
|
||||
//
|
||||
// //Determine image xform
|
||||
// xform = new AffineTransform();
|
||||
//// xform.setToScale(this.width / img.getWidth(), this.height / img.getHeight());
|
||||
//// xform.translate(this.x, this.y);
|
||||
// xform.translate(this.x, this.y);
|
||||
// xform.scale(this.width / img.getWidth(), this.height / img.getHeight());
|
||||
//
|
||||
// bounds = new Rectangle2D.Float(this.x, this.y, this.width, this.height);
|
||||
// }
|
||||
//
|
||||
// return true;
|
||||
}
|
||||
|
||||
return changeState || shapeChange;
|
||||
}
|
||||
}
|
185
graphics-svg/src/main/java/org/xbib/graphics/svg/Line.java
Normal file
185
graphics-svg/src/main/java/org/xbib/graphics/svg/Line.java
Normal file
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 5:25 PM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Line extends ShapeElement
|
||||
{
|
||||
public static final String TAG_NAME = "line";
|
||||
|
||||
float x1 = 0f;
|
||||
float y1 = 0f;
|
||||
float x2 = 0f;
|
||||
float y2 = 0f;
|
||||
Line2D.Float line;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Rect
|
||||
*/
|
||||
public Line()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("x1")))
|
||||
{
|
||||
x1 = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y1")))
|
||||
{
|
||||
y1 = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("x2")))
|
||||
{
|
||||
x2 = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y2")))
|
||||
{
|
||||
y2 = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
line = new Line2D.Float(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRender(Graphics2D g) throws SVGException
|
||||
{
|
||||
beginLayer(g);
|
||||
renderShape(g, line);
|
||||
finishLayer(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getShape()
|
||||
{
|
||||
return shapeToParent(line);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBoundingBox() throws SVGException
|
||||
{
|
||||
return boundsToParent(includeStrokeInBounds(line.getBounds2D()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean shapeChange = false;
|
||||
|
||||
if (getPres(sty.setName("x1")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != x1)
|
||||
{
|
||||
x1 = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y1")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != y1)
|
||||
{
|
||||
y1 = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("x2")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != x2)
|
||||
{
|
||||
x2 = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y2")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != y2)
|
||||
{
|
||||
y2 = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shapeChange)
|
||||
{
|
||||
build();
|
||||
}
|
||||
|
||||
return changeState || shapeChange;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 1:54 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Color;
|
||||
import java.awt.LinearGradientPaint;
|
||||
import java.awt.MultipleGradientPaint;
|
||||
import java.awt.Paint;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class LinearGradient extends Gradient
|
||||
{
|
||||
public static final String TAG_NAME = "lineargradient";
|
||||
|
||||
float x1 = 0f;
|
||||
float y1 = 0f;
|
||||
float x2 = 1f;
|
||||
float y2 = 0f;
|
||||
|
||||
/**
|
||||
* Creates a new instance of LinearGradient
|
||||
*/
|
||||
public LinearGradient()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("x1")))
|
||||
{
|
||||
x1 = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y1")))
|
||||
{
|
||||
y1 = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("x2")))
|
||||
{
|
||||
x2 = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y2")))
|
||||
{
|
||||
y2 = sty.getFloatValueWithUnits();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Paint getPaint(Rectangle2D bounds, AffineTransform xform)
|
||||
{
|
||||
MultipleGradientPaint.CycleMethod method;
|
||||
switch (spreadMethod)
|
||||
{
|
||||
default:
|
||||
case SM_PAD:
|
||||
method = MultipleGradientPaint.CycleMethod.NO_CYCLE;
|
||||
break;
|
||||
case SM_REPEAT:
|
||||
method = MultipleGradientPaint.CycleMethod.REPEAT;
|
||||
break;
|
||||
case SM_REFLECT:
|
||||
method = MultipleGradientPaint.CycleMethod.REFLECT;
|
||||
break;
|
||||
}
|
||||
|
||||
Paint paint;
|
||||
Point2D.Float pt1 = new Point2D.Float(x1, y1);
|
||||
Point2D.Float pt2 = new Point2D.Float(x2, y2);
|
||||
if (pt1.equals(pt2))
|
||||
{
|
||||
Color[] colors = getStopColors();
|
||||
paint = colors.length > 0 ? colors[0] : Color.black;
|
||||
} else if (gradientUnits == GU_USER_SPACE_ON_USE)
|
||||
{
|
||||
paint = new LinearGradientPaint(
|
||||
pt1,
|
||||
pt2,
|
||||
getStopFractions(),
|
||||
getStopColors(),
|
||||
method,
|
||||
MultipleGradientPaint.ColorSpaceType.SRGB,
|
||||
gradientTransform == null
|
||||
? new AffineTransform()
|
||||
: gradientTransform);
|
||||
} else
|
||||
{
|
||||
AffineTransform viewXform = new AffineTransform();
|
||||
viewXform.translate(bounds.getX(), bounds.getY());
|
||||
|
||||
//This is a hack to get around shapes that have a width or height of 0. Should be close enough to the true answer.
|
||||
double width = Math.max(1, bounds.getWidth());
|
||||
double height = Math.max(1, bounds.getHeight());
|
||||
viewXform.scale(width, height);
|
||||
|
||||
if (gradientTransform != null)
|
||||
{
|
||||
viewXform.concatenate(gradientTransform);
|
||||
}
|
||||
|
||||
paint = new LinearGradientPaint(
|
||||
pt1,
|
||||
pt2,
|
||||
getStopFractions(),
|
||||
getStopColors(),
|
||||
method,
|
||||
MultipleGradientPaint.ColorSpaceType.SRGB,
|
||||
viewXform);
|
||||
}
|
||||
|
||||
return paint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return stopChange;
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean shapeChange = false;
|
||||
|
||||
if (getPres(sty.setName("x1")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != x1)
|
||||
{
|
||||
x1 = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y1")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != y1)
|
||||
{
|
||||
y1 = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("x2")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != x2)
|
||||
{
|
||||
x2 = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y2")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != y2)
|
||||
{
|
||||
y2 = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
return changeState || shapeChange;
|
||||
}
|
||||
}
|
376
graphics-svg/src/main/java/org/xbib/graphics/svg/Marker.java
Normal file
376
graphics-svg/src/main/java/org/xbib/graphics/svg/Marker.java
Normal file
|
@ -0,0 +1,376 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class Marker extends Group
|
||||
{
|
||||
public static final String TAG_NAME = "marker";
|
||||
|
||||
AffineTransform viewXform;
|
||||
AffineTransform markerXform;
|
||||
Rectangle2D viewBox;
|
||||
float refX;
|
||||
float refY;
|
||||
float markerWidth = 1;
|
||||
float markerHeight = 1;
|
||||
float orient = Float.NaN;
|
||||
boolean markerUnitsStrokeWidth = true; //if set to false 'userSpaceOnUse' is assumed
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("refX")))
|
||||
{
|
||||
refX = sty.getFloatValueWithUnits();
|
||||
}
|
||||
if (getPres(sty.setName("refY")))
|
||||
{
|
||||
refY = sty.getFloatValueWithUnits();
|
||||
}
|
||||
if (getPres(sty.setName("markerWidth")))
|
||||
{
|
||||
markerWidth = sty.getFloatValueWithUnits();
|
||||
}
|
||||
if (getPres(sty.setName("markerHeight")))
|
||||
{
|
||||
markerHeight = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("orient")))
|
||||
{
|
||||
if ("auto".equals(sty.getStringValue()))
|
||||
{
|
||||
orient = Float.NaN;
|
||||
} else
|
||||
{
|
||||
orient = sty.getFloatValue();
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("viewBox")))
|
||||
{
|
||||
float[] dim = sty.getFloatList();
|
||||
viewBox = new Rectangle2D.Float(dim[0], dim[1], dim[2], dim[3]);
|
||||
}
|
||||
|
||||
if (viewBox == null)
|
||||
{
|
||||
viewBox = new Rectangle(0, 0, 1, 1);
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("markerUnits")))
|
||||
{
|
||||
String markerUnits = sty.getStringValue();
|
||||
if (markerUnits != null && markerUnits.equals("userSpaceOnUse"))
|
||||
{
|
||||
markerUnitsStrokeWidth = false;
|
||||
}
|
||||
}
|
||||
|
||||
//Transform pattern onto unit square
|
||||
viewXform = new AffineTransform();
|
||||
viewXform.scale(1.0 / viewBox.getWidth(), 1.0 / viewBox.getHeight());
|
||||
viewXform.translate(-viewBox.getX(), -viewBox.getY());
|
||||
|
||||
markerXform = new AffineTransform();
|
||||
markerXform.scale(markerWidth, markerHeight);
|
||||
markerXform.concatenate(viewXform);
|
||||
markerXform.translate(-refX, -refY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean outsideClip(Graphics2D g) throws SVGException
|
||||
{
|
||||
Shape clip = g.getClip();
|
||||
Rectangle2D rect = super.getBoundingBox();
|
||||
if (clip == null || clip.intersects(rect))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRender(Graphics2D g) throws SVGException
|
||||
{
|
||||
AffineTransform oldXform = g.getTransform();
|
||||
g.transform(markerXform);
|
||||
|
||||
super.doRender(g);
|
||||
|
||||
g.setTransform(oldXform);
|
||||
}
|
||||
|
||||
public void render(Graphics2D g, MarkerPos pos, float strokeWidth) throws SVGException
|
||||
{
|
||||
AffineTransform cacheXform = g.getTransform();
|
||||
|
||||
g.translate(pos.x, pos.y);
|
||||
if (markerUnitsStrokeWidth)
|
||||
{
|
||||
g.scale(strokeWidth, strokeWidth);
|
||||
}
|
||||
|
||||
g.rotate(Math.atan2(pos.dy, pos.dx));
|
||||
|
||||
g.transform(markerXform);
|
||||
|
||||
super.doRender(g);
|
||||
|
||||
g.setTransform(cacheXform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getShape()
|
||||
{
|
||||
Shape shape = super.getShape();
|
||||
return markerXform.createTransformedShape(shape);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBoundingBox() throws SVGException
|
||||
{
|
||||
Rectangle2D rect = super.getBoundingBox();
|
||||
return markerXform.createTransformedShape(rect).getBounds2D();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
|
||||
build();
|
||||
|
||||
//Marker properties do not change
|
||||
return changeState;
|
||||
}
|
||||
|
||||
//--------------------------------
|
||||
public static final int MARKER_START = 0;
|
||||
public static final int MARKER_MID = 1;
|
||||
public static final int MARKER_END = 2;
|
||||
|
||||
public static class MarkerPos
|
||||
{
|
||||
|
||||
int type;
|
||||
double x;
|
||||
double y;
|
||||
double dx;
|
||||
double dy;
|
||||
|
||||
public MarkerPos(int type, double x, double y, double dx, double dy)
|
||||
{
|
||||
this.type = type;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.dx = dx;
|
||||
this.dy = dy;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MarkerLayout
|
||||
{
|
||||
|
||||
private ArrayList<MarkerPos> markerList = new ArrayList<MarkerPos>();
|
||||
boolean started = false;
|
||||
|
||||
public void layout(Shape shape)
|
||||
{
|
||||
double px = 0;
|
||||
double py = 0;
|
||||
double[] coords = new double[6];
|
||||
for (PathIterator it = shape.getPathIterator(null);
|
||||
!it.isDone(); it.next())
|
||||
{
|
||||
switch (it.currentSegment(coords))
|
||||
{
|
||||
case PathIterator.SEG_MOVETO:
|
||||
px = coords[0];
|
||||
py = coords[1];
|
||||
started = false;
|
||||
break;
|
||||
case PathIterator.SEG_CLOSE:
|
||||
started = false;
|
||||
break;
|
||||
case PathIterator.SEG_LINETO:
|
||||
{
|
||||
double x = coords[0];
|
||||
double y = coords[1];
|
||||
markerIn(px, py, x - px, y - py);
|
||||
markerOut(x, y, x - px, y - py);
|
||||
px = x;
|
||||
py = y;
|
||||
break;
|
||||
}
|
||||
case PathIterator.SEG_QUADTO:
|
||||
{
|
||||
double k0x = coords[0];
|
||||
double k0y = coords[1];
|
||||
double x = coords[2];
|
||||
double y = coords[3];
|
||||
|
||||
|
||||
//Best in tangent
|
||||
if (px != k0x || py != k0y)
|
||||
{
|
||||
markerIn(px, py, k0x - px, k0y - py);
|
||||
} else
|
||||
{
|
||||
markerIn(px, py, x - px, y - py);
|
||||
}
|
||||
|
||||
//Best out tangent
|
||||
if (x != k0x || y != k0y)
|
||||
{
|
||||
markerOut(x, y, x - k0x, y - k0y);
|
||||
} else
|
||||
{
|
||||
markerOut(x, y, x - px, y - py);
|
||||
}
|
||||
|
||||
markerIn(px, py, k0x - px, k0y - py);
|
||||
markerOut(x, y, x - k0x, y - k0y);
|
||||
px = x;
|
||||
py = y;
|
||||
break;
|
||||
}
|
||||
case PathIterator.SEG_CUBICTO:
|
||||
{
|
||||
double k0x = coords[0];
|
||||
double k0y = coords[1];
|
||||
double k1x = coords[2];
|
||||
double k1y = coords[3];
|
||||
double x = coords[4];
|
||||
double y = coords[5];
|
||||
|
||||
//Best in tangent
|
||||
if (px != k0x || py != k0y)
|
||||
{
|
||||
markerIn(px, py, k0x - px, k0y - py);
|
||||
} else if (px != k1x || py != k1y)
|
||||
{
|
||||
markerIn(px, py, k1x - px, k1y - py);
|
||||
} else
|
||||
{
|
||||
markerIn(px, py, x - px, y - py);
|
||||
}
|
||||
|
||||
//Best out tangent
|
||||
if (x != k1x || y != k1y)
|
||||
{
|
||||
markerOut(x, y, x - k1x, y - k1y);
|
||||
} else if (x != k0x || y != k0y)
|
||||
{
|
||||
markerOut(x, y, x - k0x, y - k0y);
|
||||
} else
|
||||
{
|
||||
markerOut(x, y, x - px, y - py);
|
||||
}
|
||||
px = x;
|
||||
py = y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < markerList.size(); ++i)
|
||||
{
|
||||
MarkerPos prev = (MarkerPos) markerList.get(i - 1);
|
||||
MarkerPos cur = (MarkerPos) markerList.get(i);
|
||||
|
||||
if (cur.type == MARKER_START)
|
||||
{
|
||||
prev.type = MARKER_END;
|
||||
}
|
||||
}
|
||||
MarkerPos last = (MarkerPos) markerList.get(markerList.size() - 1);
|
||||
last.type = MARKER_END;
|
||||
}
|
||||
|
||||
private void markerIn(double x, double y, double dx, double dy)
|
||||
{
|
||||
if (started == false)
|
||||
{
|
||||
started = true;
|
||||
markerList.add(new MarkerPos(MARKER_START, x, y, dx, dy));
|
||||
}
|
||||
}
|
||||
|
||||
private void markerOut(double x, double y, double dx, double dy)
|
||||
{
|
||||
markerList.add(new MarkerPos(MARKER_MID, x, y, dx, dy));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the markerList
|
||||
*/
|
||||
public ArrayList<MarkerPos> getMarkerList()
|
||||
{
|
||||
return markerList;
|
||||
}
|
||||
}
|
||||
}
|
212
graphics-svg/src/main/java/org/xbib/graphics/svg/Mask.java
Normal file
212
graphics-svg/src/main/java/org/xbib/graphics/svg/Mask.java
Normal file
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.CompositeContext;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implements the mask element.
|
||||
*
|
||||
* @author Jannis Weis
|
||||
*/
|
||||
public class Mask extends Group
|
||||
{
|
||||
public static final String TAG_NAME = "mask";
|
||||
|
||||
@Override
|
||||
public String getTagName() {
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Graphics2D g)
|
||||
{
|
||||
}
|
||||
|
||||
public Composite createMaskComposite()
|
||||
{
|
||||
return new MaskComposite();
|
||||
}
|
||||
|
||||
@Override
|
||||
void pick(Point2D point, boolean boundingBox, List<List<SVGElement>> retVec)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
void pick(Rectangle2D pickArea, AffineTransform ltw, boolean boundingBox, List<List<SVGElement>> retVec)
|
||||
{
|
||||
}
|
||||
|
||||
public void pickElement(Point2D point, boolean boundingBox,
|
||||
List<List<SVGElement>> retVec, RenderableElement element) throws SVGException
|
||||
{
|
||||
if (boundingBox)
|
||||
{
|
||||
element.doPick(point, true, retVec);
|
||||
} else
|
||||
{
|
||||
Rectangle pickPoint = new Rectangle((int) point.getX(), (int) point.getY(), 1, 1);
|
||||
BufferedImage img = BufferPainter.paintToBuffer(null, new AffineTransform(), pickPoint, this, Color.BLACK);
|
||||
// Only try picking the element if the picked point is visible.
|
||||
if (luminanceToAlpha(img.getRGB(0, 0)) > 0)
|
||||
{
|
||||
element.doPick(point, false, retVec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void pickElement(Rectangle2D pickArea, AffineTransform ltw, boolean boundingBox,
|
||||
List<List<SVGElement>> retVec, RenderableElement element) throws SVGException
|
||||
{
|
||||
// If at any point the considered picking area becomes empty we break out early.
|
||||
if (pickArea.isEmpty()) return;
|
||||
if (boundingBox)
|
||||
{
|
||||
element.doPick(pickArea, ltw,true, retVec);
|
||||
} else
|
||||
{
|
||||
// Clip with the element bounds to avoid creating a larger buffer than needed.
|
||||
Area transformedBounds = new Area(ltw.createTransformedShape(element.getBoundingBox()));
|
||||
transformedBounds.intersect(new Area(pickArea));
|
||||
if (transformedBounds.isEmpty()) return;
|
||||
|
||||
Rectangle pickRect = transformedBounds.getBounds();
|
||||
if (pickRect.isEmpty()) return;
|
||||
|
||||
BufferedImage maskArea = BufferPainter.paintToBuffer(null, ltw, pickRect,this, Color.BLACK);
|
||||
|
||||
// Pick if any pixel in the pick area is visible.
|
||||
if (hasVisiblePixel(maskArea))
|
||||
{
|
||||
element.doPick(pickArea, ltw, false, retVec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasVisiblePixel(BufferedImage img)
|
||||
{
|
||||
Raster raster = img.getRaster();
|
||||
int x = raster.getMinX();
|
||||
int w = raster.getWidth();
|
||||
int y = raster.getMinY();
|
||||
int h = raster.getHeight();
|
||||
int[] srcPix = raster.getPixels(x, y, w, h, (int[]) null);
|
||||
boolean hasVisiblePixel = false;
|
||||
for (int i = 0; i < srcPix.length; i += 4)
|
||||
{
|
||||
int sr = srcPix[i];
|
||||
int sg = srcPix[i + 1];
|
||||
int sb = srcPix[i + 2];
|
||||
if (luminanceToAlpha(sr, sg, sb) > 0)
|
||||
{
|
||||
hasVisiblePixel = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return hasVisiblePixel;
|
||||
}
|
||||
|
||||
private static double luminanceToAlpha(int rgb)
|
||||
{
|
||||
return luminanceToAlpha((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF);
|
||||
}
|
||||
|
||||
private static double luminanceToAlpha(int r, int g, int b)
|
||||
{
|
||||
// Assuming 'linearRGB' as the 'color-interpolation' value of the mask.
|
||||
return 0.2125 * r + 0.7154 * g + 0.0721 * b;
|
||||
}
|
||||
|
||||
private static class MaskComposite implements Composite, CompositeContext
|
||||
{
|
||||
|
||||
@Override
|
||||
public CompositeContext createContext(ColorModel srcColorModel,
|
||||
ColorModel dstColorModel, RenderingHints hints)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public void composeRGB(int[] src, int[] dst)
|
||||
{
|
||||
int w = src.length;
|
||||
|
||||
for (int i = 0; i < w; i += 4)
|
||||
{
|
||||
int sr = src[i];
|
||||
int sg = src[i + 1];
|
||||
int sb = src[i + 2];
|
||||
int da = dst[i + 3];
|
||||
double luminance = luminanceToAlpha(sr, sg, sb) / 255d;
|
||||
da *= luminance;
|
||||
dst[i + 3] = Math.min(255, Math.max(0, da));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
|
||||
assert dstIn == dstOut;
|
||||
assert src.getNumBands() == dstIn.getNumBands();
|
||||
|
||||
int x = dstOut.getMinX();
|
||||
int w = dstOut.getWidth();
|
||||
int y = dstOut.getMinY();
|
||||
int h = dstOut.getHeight();
|
||||
int[] srcPix = src.getPixels(x, y, w, h, (int[]) null);
|
||||
int[] dstPix = dstIn.getPixels(x, y, w, h, (int[]) null);
|
||||
composeRGB(srcPix, dstPix);
|
||||
dstOut.setPixels(x, y, w, h, dstPix);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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 September 19, 2004, 1:56 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
/**
|
||||
* Does not hold any information. Included to allow metadata tag to be parsed.
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Metadata extends SVGElement
|
||||
{
|
||||
public static final String TAG_NAME = "metadata";
|
||||
|
||||
/**
|
||||
* Creates a new instance of Stop
|
||||
*/
|
||||
public Metadata()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTime(double curTime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* 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 20, 2004, 10:00 PM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.pathcmd.BuildHistory;
|
||||
import org.xbib.graphics.svg.pathcmd.PathCommand;
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Implements an embedded font.
|
||||
*
|
||||
* SVG specification: http://www.w3.org/TR/SVG/fonts.html
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class MissingGlyph extends ShapeElement
|
||||
{
|
||||
public static final String TAG_NAME = "missingglyph";
|
||||
|
||||
//We may define a path
|
||||
private Shape path = null;
|
||||
//Alternately, we may have child graphical elements
|
||||
private float horizAdvX = -1; //Inherits font's value if not set
|
||||
private float vertOriginX = -1; //Inherits font's value if not set
|
||||
private float vertOriginY = -1; //Inherits font's value if not set
|
||||
private float vertAdvY = -1; //Inherits font's value if not set
|
||||
|
||||
/**
|
||||
* Creates a new instance of Font
|
||||
*/
|
||||
public MissingGlyph()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the start element but before the end element to indicate
|
||||
* each child tag that has been processed
|
||||
*/
|
||||
@Override
|
||||
public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
|
||||
{
|
||||
super.loaderAddChild(helper, child);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
String commandList = "";
|
||||
if (getPres(sty.setName("d")))
|
||||
{
|
||||
commandList = sty.getStringValue();
|
||||
}
|
||||
|
||||
|
||||
//If glyph path was specified, calculate it
|
||||
if (commandList != null)
|
||||
{
|
||||
String fillRule = getStyle(sty.setName("fill-rule")) ? sty.getStringValue() : "nonzero";
|
||||
|
||||
PathCommand[] commands = parsePathList(commandList);
|
||||
|
||||
GeneralPath buildPath = new GeneralPath(
|
||||
fillRule.equals("evenodd") ? GeneralPath.WIND_EVEN_ODD : GeneralPath.WIND_NON_ZERO,
|
||||
commands.length);
|
||||
|
||||
BuildHistory hist = new BuildHistory();
|
||||
|
||||
for (int i = 0; i < commands.length; i++)
|
||||
{
|
||||
PathCommand cmd = commands[i];
|
||||
cmd.appendPath(buildPath, hist);
|
||||
}
|
||||
|
||||
//Reflect glyph path to put it in user coordinate system
|
||||
AffineTransform at = new AffineTransform();
|
||||
at.scale(1, -1);
|
||||
path = at.createTransformedShape(buildPath);
|
||||
}
|
||||
|
||||
|
||||
//Read glyph spacing info
|
||||
if (getPres(sty.setName("horiz-adv-x")))
|
||||
{
|
||||
horizAdvX = sty.getFloatValue();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("vert-origin-x")))
|
||||
{
|
||||
vertOriginX = sty.getFloatValue();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("vert-origin-y")))
|
||||
{
|
||||
vertOriginY = sty.getFloatValue();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("vert-adv-y")))
|
||||
{
|
||||
vertAdvY = sty.getFloatValue();
|
||||
}
|
||||
}
|
||||
|
||||
public Shape getPath()
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRender(Graphics2D g) throws SVGException
|
||||
{
|
||||
//Do not push or pop stack
|
||||
|
||||
if (path != null)
|
||||
{
|
||||
renderShape(g, path);
|
||||
}
|
||||
|
||||
Iterator<SVGElement> it = children.iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
SVGElement ele = it.next();
|
||||
if (ele instanceof RenderableElement)
|
||||
{
|
||||
((RenderableElement) ele).render(g);
|
||||
}
|
||||
}
|
||||
|
||||
//Do not push or pop stack
|
||||
}
|
||||
|
||||
public float getHorizAdvX()
|
||||
{
|
||||
if (horizAdvX == -1)
|
||||
{
|
||||
horizAdvX = ((Font) parent).getHorizAdvX();
|
||||
}
|
||||
return horizAdvX;
|
||||
}
|
||||
|
||||
public float getVertOriginX()
|
||||
{
|
||||
if (vertOriginX == -1)
|
||||
{
|
||||
vertOriginX = getHorizAdvX() / 2;
|
||||
}
|
||||
return vertOriginX;
|
||||
}
|
||||
|
||||
public float getVertOriginY()
|
||||
{
|
||||
if (vertOriginY == -1)
|
||||
{
|
||||
vertOriginY = ((Font) parent).getFontFace().getAscent();
|
||||
}
|
||||
return vertOriginY;
|
||||
}
|
||||
|
||||
public float getVertAdvY()
|
||||
{
|
||||
if (vertAdvY == -1)
|
||||
{
|
||||
vertAdvY = ((Font) parent).getFontFace().getUnitsPerEm();
|
||||
}
|
||||
return vertAdvY;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getShape()
|
||||
{
|
||||
if (path != null)
|
||||
{
|
||||
return shapeToParent(path);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBoundingBox() throws SVGException
|
||||
{
|
||||
if (path != null)
|
||||
{
|
||||
return boundsToParent(includeStrokeInBounds(path.getBounds2D()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
//Fonts can't change
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param path the path to set
|
||||
*/
|
||||
public void setPath(Shape path)
|
||||
{
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param horizAdvX the horizAdvX to set
|
||||
*/
|
||||
public void setHorizAdvX(float horizAdvX)
|
||||
{
|
||||
this.horizAdvX = horizAdvX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param vertOriginX the vertOriginX to set
|
||||
*/
|
||||
public void setVertOriginX(float vertOriginX)
|
||||
{
|
||||
this.vertOriginX = vertOriginX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param vertOriginY the vertOriginY to set
|
||||
*/
|
||||
public void setVertOriginY(float vertOriginY)
|
||||
{
|
||||
this.vertOriginY = vertOriginY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param vertAdvY the vertAdvY to set
|
||||
*/
|
||||
public void setVertAdvY(float vertAdvY)
|
||||
{
|
||||
this.vertAdvY = vertAdvY;
|
||||
}
|
||||
}
|
158
graphics-svg/src/main/java/org/xbib/graphics/svg/Path.java
Normal file
158
graphics-svg/src/main/java/org/xbib/graphics/svg/Path.java
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 5:25 PM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Path extends ShapeElement
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "path";
|
||||
// PathCommand[] commands = null;
|
||||
int fillRule = GeneralPath.WIND_NON_ZERO;
|
||||
String d = "";
|
||||
// ExtendedGeneralPath path;
|
||||
GeneralPath path;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Rect
|
||||
*/
|
||||
public Path()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
|
||||
String fillRuleStrn = (getStyle(sty.setName("fill-rule"))) ? sty.getStringValue() : "nonzero";
|
||||
fillRule = fillRuleStrn.equals("evenodd") ? GeneralPath.WIND_EVEN_ODD : GeneralPath.WIND_NON_ZERO;
|
||||
|
||||
if (getPres(sty.setName("d")))
|
||||
{
|
||||
d = sty.getStringValue();
|
||||
}
|
||||
|
||||
path = buildPath(d, fillRule);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRender(Graphics2D g) throws SVGException
|
||||
{
|
||||
beginLayer(g);
|
||||
renderShape(g, path);
|
||||
finishLayer(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getShape()
|
||||
{
|
||||
return shapeToParent(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBoundingBox() throws SVGException
|
||||
{
|
||||
return boundsToParent(includeStrokeInBounds(path.getBounds2D()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean shapeChange = false;
|
||||
|
||||
if (getStyle(sty.setName("fill-rule")))
|
||||
{
|
||||
int newVal = sty.getStringValue().equals("evenodd")
|
||||
? GeneralPath.WIND_EVEN_ODD
|
||||
: GeneralPath.WIND_NON_ZERO;
|
||||
if (newVal != fillRule)
|
||||
{
|
||||
fillRule = newVal;
|
||||
changeState = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("d")))
|
||||
{
|
||||
String newVal = sty.getStringValue();
|
||||
if (!newVal.equals(d))
|
||||
{
|
||||
d = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shapeChange)
|
||||
{
|
||||
build();
|
||||
// path = buildPath(d, fillRule);
|
||||
// return true;
|
||||
}
|
||||
|
||||
return changeState || shapeChange;
|
||||
}
|
||||
}
|
285
graphics-svg/src/main/java/org/xbib/graphics/svg/PatternSVG.java
Normal file
285
graphics-svg/src/main/java/org/xbib/graphics/svg/PatternSVG.java
Normal file
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 3:25 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.pattern.PatternPaint;
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Paint;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.TexturePaint;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.net.URI;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class PatternSVG extends FillElement
|
||||
{
|
||||
public static final String TAG_NAME = "pattern";
|
||||
|
||||
public static final int GU_OBJECT_BOUNDING_BOX = 0;
|
||||
public static final int GU_USER_SPACE_ON_USE = 1;
|
||||
int gradientUnits = GU_OBJECT_BOUNDING_BOX;
|
||||
float x;
|
||||
float y;
|
||||
float width;
|
||||
float height;
|
||||
AffineTransform patternXform = new AffineTransform();
|
||||
Rectangle2D.Float viewBox;
|
||||
Paint texPaint;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Gradient
|
||||
*/
|
||||
public PatternSVG()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the start element but before the end element to indicate
|
||||
* each child tag that has been processed
|
||||
*/
|
||||
@Override
|
||||
public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
|
||||
{
|
||||
super.loaderAddChild(helper, child);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
//Load style string
|
||||
String href = null;
|
||||
if (getPres(sty.setName("xlink:href")))
|
||||
{
|
||||
href = sty.getStringValue();
|
||||
}
|
||||
//String href = attrs.getValue("xlink:href");
|
||||
//If we have a link to another pattern, initialize ourselves with it's values
|
||||
if (href != null)
|
||||
{
|
||||
//System.err.println("Gradient.loaderStartElement() href '" + href + "'");
|
||||
try
|
||||
{
|
||||
URI src = getXMLBase().resolve(href);
|
||||
PatternSVG patSrc = (PatternSVG) diagram.getUniverse().getElement(src);
|
||||
|
||||
gradientUnits = patSrc.gradientUnits;
|
||||
x = patSrc.x;
|
||||
y = patSrc.y;
|
||||
width = patSrc.width;
|
||||
height = patSrc.height;
|
||||
viewBox = patSrc.viewBox;
|
||||
patternXform.setTransform(patSrc.patternXform);
|
||||
children.addAll(patSrc.children);
|
||||
} catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not parse xlink:href", e);
|
||||
}
|
||||
}
|
||||
|
||||
String gradientUnits = "";
|
||||
if (getPres(sty.setName("gradientUnits")))
|
||||
{
|
||||
gradientUnits = sty.getStringValue().toLowerCase();
|
||||
}
|
||||
if (gradientUnits.equals("userspaceonuse"))
|
||||
{
|
||||
this.gradientUnits = GU_USER_SPACE_ON_USE;
|
||||
} else
|
||||
{
|
||||
this.gradientUnits = GU_OBJECT_BOUNDING_BOX;
|
||||
}
|
||||
|
||||
String patternTransform = "";
|
||||
if (getPres(sty.setName("patternTransform")))
|
||||
{
|
||||
patternTransform = sty.getStringValue();
|
||||
}
|
||||
patternXform = parseTransform(patternTransform);
|
||||
|
||||
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
x = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
y = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("width")))
|
||||
{
|
||||
width = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("height")))
|
||||
{
|
||||
height = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("viewBox")))
|
||||
{
|
||||
float[] dim = sty.getFloatList();
|
||||
viewBox = new Rectangle2D.Float(dim[0], dim[1], dim[2], dim[3]);
|
||||
}
|
||||
|
||||
preparePattern();
|
||||
}
|
||||
|
||||
/*
|
||||
public void loaderEndElement(SVGLoaderHelper helper)
|
||||
{
|
||||
build();
|
||||
}
|
||||
*/
|
||||
protected void preparePattern() throws SVGException
|
||||
{
|
||||
//For now, treat all fills as UserSpaceOnUse. Otherwise, we'll need
|
||||
// a different paint for every object.
|
||||
int tileWidth = (int) width;
|
||||
int tileHeight = (int) height;
|
||||
|
||||
float stretchX = 1f, stretchY = 1f;
|
||||
if (!patternXform.isIdentity())
|
||||
{
|
||||
//Scale our source tile so that we can have nice sampling from it.
|
||||
float xlateX = (float) patternXform.getTranslateX();
|
||||
float xlateY = (float) patternXform.getTranslateY();
|
||||
|
||||
Point2D.Float pt = new Point2D.Float(), pt2 = new Point2D.Float();
|
||||
|
||||
pt.setLocation(width, 0);
|
||||
patternXform.transform(pt, pt2);
|
||||
pt2.x -= xlateX;
|
||||
pt2.y -= xlateY;
|
||||
stretchX = (float) Math.sqrt(pt2.x * pt2.x + pt2.y * pt2.y) * 1.5f / width;
|
||||
|
||||
pt.setLocation(height, 0);
|
||||
patternXform.transform(pt, pt2);
|
||||
pt2.x -= xlateX;
|
||||
pt2.y -= xlateY;
|
||||
stretchY = (float) Math.sqrt(pt2.x * pt2.x + pt2.y * pt2.y) * 1.5f / height;
|
||||
|
||||
tileWidth *= stretchX;
|
||||
tileHeight *= stretchY;
|
||||
}
|
||||
|
||||
if (tileWidth == 0 || tileHeight == 0)
|
||||
{
|
||||
//Use defaults if tile has degenerate size
|
||||
return;
|
||||
}
|
||||
|
||||
BufferedImage buf = new BufferedImage(tileWidth, tileHeight, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g = buf.createGraphics();
|
||||
g.setClip(0, 0, tileWidth, tileHeight);
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
for (SVGElement ele : children) {
|
||||
if (ele instanceof RenderableElement)
|
||||
{
|
||||
AffineTransform xform = new AffineTransform();
|
||||
|
||||
if (viewBox == null)
|
||||
{
|
||||
xform.translate(-x, -y);
|
||||
} else
|
||||
{
|
||||
xform.scale(tileWidth / viewBox.width, tileHeight / viewBox.height);
|
||||
xform.translate(-viewBox.x, -viewBox.y);
|
||||
}
|
||||
|
||||
g.setTransform(xform);
|
||||
((RenderableElement) ele).render(g);
|
||||
}
|
||||
}
|
||||
|
||||
g.dispose();
|
||||
|
||||
//try {
|
||||
//javax.imageio.ImageIO.write(buf, "png", new java.io.File("c:\\tmp\\texPaint.png"));
|
||||
//} catch (Exception e ) {}
|
||||
|
||||
if (patternXform.isIdentity())
|
||||
{
|
||||
texPaint = new TexturePaint(buf, new Rectangle2D.Float(x, y, width, height));
|
||||
} else
|
||||
{
|
||||
patternXform.scale(1 / stretchX, 1 / stretchY);
|
||||
texPaint = new PatternPaint(buf, patternXform);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Paint getPaint(Rectangle2D bounds, AffineTransform xform)
|
||||
{
|
||||
return texPaint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
//Patterns don't change state
|
||||
return false;
|
||||
}
|
||||
}
|
170
graphics-svg/src/main/java/org/xbib/graphics/svg/Polygon.java
Normal file
170
graphics-svg/src/main/java/org/xbib/graphics/svg/Polygon.java
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 5:25 PM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import org.xbib.graphics.svg.xml.XMLParseUtil;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Polygon extends ShapeElement
|
||||
{
|
||||
public static final String TAG_NAME = "polygon";
|
||||
|
||||
int fillRule = GeneralPath.WIND_NON_ZERO;
|
||||
String pointsStrn = "";
|
||||
GeneralPath path;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Rect
|
||||
*/
|
||||
public Polygon()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("points")))
|
||||
{
|
||||
pointsStrn = sty.getStringValue();
|
||||
}
|
||||
|
||||
String fillRuleStrn = getStyle(sty.setName("fill-rule")) ? sty.getStringValue() : "nonzero";
|
||||
fillRule = fillRuleStrn.equals("evenodd") ? GeneralPath.WIND_EVEN_ODD : GeneralPath.WIND_NON_ZERO;
|
||||
|
||||
buildPath();
|
||||
}
|
||||
|
||||
protected void buildPath()
|
||||
{
|
||||
float[] points = XMLParseUtil.parseFloatList(pointsStrn);
|
||||
path = new GeneralPath(fillRule, points.length / 2);
|
||||
|
||||
path.moveTo(points[0], points[1]);
|
||||
for (int i = 2; i < points.length; i += 2)
|
||||
{
|
||||
path.lineTo(points[i], points[i + 1]);
|
||||
}
|
||||
path.closePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRender(Graphics2D g) throws SVGException
|
||||
{
|
||||
beginLayer(g);
|
||||
renderShape(g, path);
|
||||
finishLayer(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getShape()
|
||||
{
|
||||
return shapeToParent(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBoundingBox() throws SVGException
|
||||
{
|
||||
return boundsToParent(includeStrokeInBounds(path.getBounds2D()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean shapeChange = false;
|
||||
|
||||
if (getStyle(sty.setName("fill-rule")))
|
||||
{
|
||||
int newVal = sty.getStringValue().equals("evenodd")
|
||||
? GeneralPath.WIND_EVEN_ODD
|
||||
: GeneralPath.WIND_NON_ZERO;
|
||||
if (newVal != fillRule)
|
||||
{
|
||||
fillRule = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("points")))
|
||||
{
|
||||
String newVal = sty.getStringValue();
|
||||
if (!newVal.equals(pointsStrn))
|
||||
{
|
||||
pointsStrn = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (shapeChange)
|
||||
{
|
||||
build();
|
||||
// buildPath();
|
||||
// return true;
|
||||
}
|
||||
|
||||
return changeState || shapeChange;
|
||||
}
|
||||
}
|
169
graphics-svg/src/main/java/org/xbib/graphics/svg/Polyline.java
Normal file
169
graphics-svg/src/main/java/org/xbib/graphics/svg/Polyline.java
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 5:25 PM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import org.xbib.graphics.svg.xml.XMLParseUtil;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Polyline extends ShapeElement
|
||||
{
|
||||
public static final String TAG_NAME = "polyline";
|
||||
|
||||
int fillRule = GeneralPath.WIND_NON_ZERO;
|
||||
String pointsStrn = "";
|
||||
GeneralPath path;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Rect
|
||||
*/
|
||||
public Polyline()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("points")))
|
||||
{
|
||||
pointsStrn = sty.getStringValue();
|
||||
}
|
||||
|
||||
String fillRuleStrn = getStyle(sty.setName("fill-rule")) ? sty.getStringValue() : "nonzero";
|
||||
fillRule = fillRuleStrn.equals("evenodd") ? GeneralPath.WIND_EVEN_ODD : GeneralPath.WIND_NON_ZERO;
|
||||
|
||||
buildPath();
|
||||
}
|
||||
|
||||
protected void buildPath()
|
||||
{
|
||||
float[] points = XMLParseUtil.parseFloatList(pointsStrn);
|
||||
path = new GeneralPath(fillRule, points.length / 2);
|
||||
|
||||
path.moveTo(points[0], points[1]);
|
||||
for (int i = 2; i < points.length; i += 2)
|
||||
{
|
||||
path.lineTo(points[i], points[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRender(Graphics2D g) throws SVGException
|
||||
{
|
||||
beginLayer(g);
|
||||
renderShape(g, path);
|
||||
finishLayer(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getShape()
|
||||
{
|
||||
return shapeToParent(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBoundingBox() throws SVGException
|
||||
{
|
||||
return boundsToParent(includeStrokeInBounds(path.getBounds2D()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean shapeChange = false;
|
||||
|
||||
if (getStyle(sty.setName("fill-rule")))
|
||||
{
|
||||
int newVal = sty.getStringValue().equals("evenodd")
|
||||
? GeneralPath.WIND_EVEN_ODD
|
||||
: GeneralPath.WIND_NON_ZERO;
|
||||
if (newVal != fillRule)
|
||||
{
|
||||
fillRule = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("points")))
|
||||
{
|
||||
String newVal = sty.getStringValue();
|
||||
if (!newVal.equals(pointsStrn))
|
||||
{
|
||||
pointsStrn = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (shapeChange)
|
||||
{
|
||||
build();
|
||||
// buildPath();
|
||||
// return true;
|
||||
}
|
||||
|
||||
return changeState || shapeChange;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 1:55 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Color;
|
||||
import java.awt.MultipleGradientPaint;
|
||||
import java.awt.Paint;
|
||||
import java.awt.RadialGradientPaint;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class RadialGradient extends Gradient
|
||||
{
|
||||
public static final String TAG_NAME = "radialgradient";
|
||||
|
||||
float cx = 0.5f;
|
||||
float cy = 0.5f;
|
||||
boolean hasFocus = false;
|
||||
float fx = 0f;
|
||||
float fy = 0f;
|
||||
float r = 0.5f;
|
||||
|
||||
/**
|
||||
* Creates a new instance of RadialGradient
|
||||
*/
|
||||
public RadialGradient()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("cx")))
|
||||
{
|
||||
cx = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("cy")))
|
||||
{
|
||||
cy = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
hasFocus = false;
|
||||
if (getPres(sty.setName("fx")))
|
||||
{
|
||||
fx = sty.getFloatValueWithUnits();
|
||||
hasFocus = true;
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("fy")))
|
||||
{
|
||||
fy = sty.getFloatValueWithUnits();
|
||||
hasFocus = true;
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("r")))
|
||||
{
|
||||
r = sty.getFloatValueWithUnits();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Paint getPaint(Rectangle2D bounds, AffineTransform xform)
|
||||
{
|
||||
MultipleGradientPaint.CycleMethod method;
|
||||
switch (spreadMethod)
|
||||
{
|
||||
default:
|
||||
case SM_PAD:
|
||||
method = MultipleGradientPaint.CycleMethod.NO_CYCLE;
|
||||
break;
|
||||
case SM_REPEAT:
|
||||
method = MultipleGradientPaint.CycleMethod.REPEAT;
|
||||
break;
|
||||
case SM_REFLECT:
|
||||
method = MultipleGradientPaint.CycleMethod.REFLECT;
|
||||
break;
|
||||
}
|
||||
|
||||
Paint paint;
|
||||
Point2D.Float pt1 = new Point2D.Float(cx, cy);
|
||||
Point2D.Float pt2 = hasFocus ? new Point2D.Float(fx, fy) : pt1;
|
||||
float[] stopFractions = getStopFractions();
|
||||
Color[] stopColors = getStopColors();
|
||||
|
||||
//Verify that the stop fractions are valid
|
||||
{
|
||||
//for (int i = 0; i <
|
||||
}
|
||||
|
||||
if (gradientUnits == GU_USER_SPACE_ON_USE)
|
||||
{
|
||||
paint = new RadialGradientPaint(
|
||||
pt1,
|
||||
r,
|
||||
pt2,
|
||||
stopFractions,
|
||||
stopColors,
|
||||
method,
|
||||
MultipleGradientPaint.ColorSpaceType.SRGB,
|
||||
gradientTransform);
|
||||
} else
|
||||
{
|
||||
AffineTransform viewXform = new AffineTransform();
|
||||
viewXform.translate(bounds.getX(), bounds.getY());
|
||||
viewXform.scale(bounds.getWidth(), bounds.getHeight());
|
||||
|
||||
viewXform.concatenate(gradientTransform);
|
||||
|
||||
paint = new RadialGradientPaint(
|
||||
pt1,
|
||||
r,
|
||||
pt2,
|
||||
stopFractions,
|
||||
stopColors,
|
||||
method,
|
||||
MultipleGradientPaint.ColorSpaceType.SRGB,
|
||||
viewXform);
|
||||
}
|
||||
|
||||
return paint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean shapeChange = false;
|
||||
|
||||
if (getPres(sty.setName("cx")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != cx)
|
||||
{
|
||||
cx = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("cy")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != cy)
|
||||
{
|
||||
cy = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("fx")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != fx)
|
||||
{
|
||||
fx = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("fy")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != fy)
|
||||
{
|
||||
fy = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("r")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != r)
|
||||
{
|
||||
r = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
return changeState;
|
||||
}
|
||||
}
|
317
graphics-svg/src/main/java/org/xbib/graphics/svg/Rect.java
Normal file
317
graphics-svg/src/main/java/org/xbib/graphics/svg/Rect.java
Normal file
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 5:25 PM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.RectangularShape;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Rect extends ShapeElement
|
||||
{
|
||||
public static final String TAG_NAME = "rect";
|
||||
|
||||
float x = 0f;
|
||||
float y = 0f;
|
||||
float width = 0f;
|
||||
float height = 0f;
|
||||
float rx = 0f;
|
||||
float ry = 0f;
|
||||
RectangularShape rect;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Rect
|
||||
*/
|
||||
public Rect()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream out) throws IOException
|
||||
{
|
||||
out.writeFloat(x);
|
||||
out.writeFloat(y);
|
||||
out.writeFloat(width);
|
||||
out.writeFloat(height);
|
||||
out.writeFloat(rx);
|
||||
out.writeFloat(ry);
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException
|
||||
{
|
||||
x = in.readFloat();
|
||||
y = in.readFloat();
|
||||
width = in.readFloat();
|
||||
height = in.readFloat();
|
||||
rx = in.readFloat();
|
||||
ry = in.readFloat();
|
||||
|
||||
if (rx == 0f && ry == 0f)
|
||||
{
|
||||
rect = new Rectangle2D.Float(x, y, width, height);
|
||||
} else
|
||||
{
|
||||
rect = new RoundRectangle2D.Float(x, y, width, height, rx * 2, ry * 2);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent)
|
||||
{
|
||||
//Load style string
|
||||
super.loaderStartElement(helper, attrs, parent);
|
||||
|
||||
String x = attrs.getValue("x");
|
||||
String y = attrs.getValue("y");
|
||||
String width = attrs.getValue("width");
|
||||
String height = attrs.getValue("height");
|
||||
String rx = attrs.getValue("rx");
|
||||
String ry = attrs.getValue("ry");
|
||||
|
||||
if (rx == null) rx = ry;
|
||||
if (ry == null) ry = rx;
|
||||
|
||||
this.x = XMLParseUtil.parseFloat(x);
|
||||
this.y = XMLParseUtil.parseFloat(y);
|
||||
this.width = XMLParseUtil.parseFloat(width);
|
||||
this.height = XMLParseUtil.parseFloat(height);
|
||||
if (rx != null)
|
||||
{
|
||||
this.rx = XMLParseUtil.parseFloat(rx);
|
||||
this.ry = XMLParseUtil.parseFloat(ry);
|
||||
}
|
||||
|
||||
build();
|
||||
// setBounds(this.x, this.y, this.width, this.height);
|
||||
}
|
||||
*/
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
// SVGElement parent = this.getParent();
|
||||
// if (parent instanceof RenderableElement)
|
||||
// {
|
||||
// RenderableElement re = (RenderableElement)parent;
|
||||
// Rectangle2D bounds = re.getBoundingBox();
|
||||
// bounds = null;
|
||||
// }
|
||||
|
||||
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
x = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
y = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("width")))
|
||||
{
|
||||
width = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("height")))
|
||||
{
|
||||
height = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
boolean rxSet = false;
|
||||
if (getPres(sty.setName("rx")))
|
||||
{
|
||||
rx = sty.getFloatValueWithUnits();
|
||||
rxSet = true;
|
||||
}
|
||||
|
||||
boolean rySet = false;
|
||||
if (getPres(sty.setName("ry")))
|
||||
{
|
||||
ry = sty.getFloatValueWithUnits();
|
||||
rySet = true;
|
||||
}
|
||||
|
||||
if (!rxSet)
|
||||
{
|
||||
rx = ry;
|
||||
}
|
||||
if (!rySet)
|
||||
{
|
||||
ry = rx;
|
||||
}
|
||||
|
||||
|
||||
if (rx == 0f && ry == 0f)
|
||||
{
|
||||
rect = new Rectangle2D.Float(x, y, width, height);
|
||||
} else
|
||||
{
|
||||
rect = new RoundRectangle2D.Float(x, y, width, height, rx * 2, ry * 2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRender(Graphics2D g) throws SVGException
|
||||
{
|
||||
beginLayer(g);
|
||||
renderShape(g, rect);
|
||||
finishLayer(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getShape()
|
||||
{
|
||||
return shapeToParent(rect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBoundingBox() throws SVGException
|
||||
{
|
||||
return boundsToParent(includeStrokeInBounds(rect.getBounds2D()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean shapeChange = false;
|
||||
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != x)
|
||||
{
|
||||
x = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != y)
|
||||
{
|
||||
y = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("width")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != width)
|
||||
{
|
||||
width = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("height")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != height)
|
||||
{
|
||||
height = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("rx")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != rx)
|
||||
{
|
||||
rx = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("ry")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != ry)
|
||||
{
|
||||
ry = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shapeChange)
|
||||
{
|
||||
build();
|
||||
// if (rx == 0f && ry == 0f)
|
||||
// {
|
||||
// rect = new Rectangle2D.Float(x, y, width, height);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// rect = new RoundRectangle2D.Float(x, y, width, height, rx * 2, ry * 2);
|
||||
// }
|
||||
// return true;
|
||||
}
|
||||
|
||||
return changeState || shapeChange;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 9:00 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Maintains bounding box for this element
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
abstract public class RenderableElement extends TransformableElement
|
||||
{
|
||||
AffineTransform cachedXform = null;
|
||||
|
||||
Mask cachedMask;
|
||||
Filter filter;
|
||||
Shape cachedClip = null;
|
||||
public static final int VECTOR_EFFECT_NONE = 0;
|
||||
public static final int VECTOR_EFFECT_NON_SCALING_STROKE = 1;
|
||||
int vectorEffect;
|
||||
|
||||
private BufferPainter.Cache bufferCache;
|
||||
|
||||
/**
|
||||
* Creates a new instance of BoundedElement
|
||||
*/
|
||||
public RenderableElement()
|
||||
{
|
||||
}
|
||||
|
||||
public RenderableElement(String id, SVGElement parent)
|
||||
{
|
||||
super(id, parent);
|
||||
}
|
||||
|
||||
BufferPainter.Cache getBufferCache()
|
||||
{
|
||||
return bufferCache;
|
||||
}
|
||||
|
||||
void setBufferImage(BufferPainter.Cache bufferCache)
|
||||
{
|
||||
this.bufferCache = bufferCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("vector-effect")))
|
||||
{
|
||||
if ("non-scaling-stroke".equals(sty.getStringValue()))
|
||||
{
|
||||
vectorEffect = VECTOR_EFFECT_NON_SCALING_STROKE;
|
||||
} else
|
||||
{
|
||||
vectorEffect = VECTOR_EFFECT_NONE;
|
||||
}
|
||||
} else
|
||||
{
|
||||
vectorEffect = VECTOR_EFFECT_NONE;
|
||||
}
|
||||
|
||||
cachedMask = getMask(sty);
|
||||
filter = getFilter(sty);
|
||||
}
|
||||
|
||||
public void render(Graphics2D g) throws SVGException
|
||||
{
|
||||
BufferPainter.paintElement(g, this);
|
||||
}
|
||||
|
||||
private Mask getMask(StyleAttribute styleAttrib) throws SVGException
|
||||
{
|
||||
if (getStyle(styleAttrib.setName("mask"), false)
|
||||
&& !"none".equals(styleAttrib.getStringValue())) {
|
||||
URI uri = styleAttrib.getURIValue(getXMLBase());
|
||||
if (uri == null) {
|
||||
return null;
|
||||
}
|
||||
return (Mask) diagram.getUniverse().getElement(uri);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Filter getFilter(StyleAttribute styleAttrib) throws SVGException
|
||||
{
|
||||
if (getStyle(styleAttrib.setName("filter"), false)
|
||||
&& !"none".equals(styleAttrib.getStringValue())) {
|
||||
URI uri = styleAttrib.getURIValue(getXMLBase());
|
||||
if (uri == null) {
|
||||
return null;
|
||||
}
|
||||
return (Filter) diagram.getUniverse().getElement(uri);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract protected void doRender(Graphics2D g) throws SVGException;
|
||||
|
||||
void pick(Point2D point, boolean boundingBox, List<List<SVGElement>> retVec) throws SVGException
|
||||
{
|
||||
if (cachedMask != null)
|
||||
{
|
||||
cachedMask.pickElement(point, boundingBox, retVec, this);
|
||||
} else
|
||||
{
|
||||
doPick(point, boundingBox, retVec);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void doPick(Point2D point, boolean boundingBox, List<List<SVGElement>> retVec) throws SVGException;
|
||||
|
||||
void pick(Rectangle2D pickArea, AffineTransform ltw, boolean boundingBox, List<List<SVGElement>> retVec) throws SVGException
|
||||
{
|
||||
if (cachedMask != null)
|
||||
{
|
||||
cachedMask.pickElement(pickArea, ltw, boundingBox, retVec, this);
|
||||
} else
|
||||
{
|
||||
doPick(pickArea, ltw, boundingBox, retVec);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void doPick(Rectangle2D pickArea, AffineTransform ltw, boolean boundingBox, List<List<SVGElement>> retVec) throws SVGException;
|
||||
|
||||
abstract public Rectangle2D getBoundingBox() throws SVGException;
|
||||
/*
|
||||
public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent)
|
||||
{
|
||||
super.loaderStartElement(helper, attrs, parent);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pushes transform stack, transforms to local coordinates and sets up
|
||||
* clipping mask.
|
||||
*
|
||||
* @param g Graphics context
|
||||
* @throws SVGException
|
||||
*/
|
||||
protected void beginLayer(Graphics2D g) throws SVGException
|
||||
{
|
||||
if (xform != null)
|
||||
{
|
||||
cachedXform = g.getTransform();
|
||||
g.transform(xform);
|
||||
}
|
||||
|
||||
StyleAttribute styleAttrib = new StyleAttribute();
|
||||
|
||||
//Get clipping path
|
||||
// StyleAttribute styleAttrib = getStyle("clip-path", false);
|
||||
Shape clipPath = null;
|
||||
int clipPathUnits = ClipPath.CP_USER_SPACE_ON_USE;
|
||||
if (getStyle(styleAttrib.setName("clip-path"), false)
|
||||
&& !"none".equals(styleAttrib.getStringValue()))
|
||||
{
|
||||
URI uri = styleAttrib.getURIValue(getXMLBase());
|
||||
if (uri != null)
|
||||
{
|
||||
ClipPath ele = (ClipPath) diagram.getUniverse().getElement(uri);
|
||||
clipPath = ele.getClipPathShape();
|
||||
clipPathUnits = ele.getClipPathUnits();
|
||||
}
|
||||
}
|
||||
|
||||
//Return if we're out of clipping range
|
||||
if (clipPath != null)
|
||||
{
|
||||
if (clipPathUnits == ClipPath.CP_OBJECT_BOUNDING_BOX && (this instanceof ShapeElement))
|
||||
{
|
||||
Rectangle2D rect = ((ShapeElement) this).getBoundingBox();
|
||||
AffineTransform at = new AffineTransform();
|
||||
at.scale(rect.getWidth(), rect.getHeight());
|
||||
clipPath = at.createTransformedShape(clipPath);
|
||||
}
|
||||
|
||||
cachedClip = g.getClip();
|
||||
if (cachedClip == null)
|
||||
{
|
||||
g.setClip(clipPath);
|
||||
} else
|
||||
{
|
||||
Area newClip = new Area(cachedClip);
|
||||
newClip.intersect(new Area(clipPath));
|
||||
g.setClip(newClip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores transform and clipping values to the way they were before this
|
||||
* layer was drawn.
|
||||
* @param g
|
||||
*/
|
||||
protected void finishLayer(Graphics2D g)
|
||||
{
|
||||
if (cachedClip != null)
|
||||
{
|
||||
g.setClip(cachedClip);
|
||||
}
|
||||
|
||||
if (cachedXform != null)
|
||||
{
|
||||
g.setTransform(cachedXform);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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 April 2, 2005, 1:54 AM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
/**
|
||||
* A convienience singleton for allowing all classes to access a common SVG universe.
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class SVGCache
|
||||
{
|
||||
private static final SVGUniverse svgUniverse = new SVGUniverse();
|
||||
|
||||
/** Creates a new instance of SVGUniverseSingleton */
|
||||
private SVGCache()
|
||||
{
|
||||
}
|
||||
|
||||
public static SVGUniverse getSVGUniverse()
|
||||
{
|
||||
return svgUniverse;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public interface SVGConst
|
||||
{
|
||||
public static final String SVG_LOGGER = "svgSalamandeLogger";
|
||||
}
|
286
graphics-svg/src/main/java/org/xbib/graphics/svg/SVGDiagram.java
Normal file
286
graphics-svg/src/main/java/org/xbib/graphics/svg/SVGDiagram.java
Normal file
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* 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:04 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.Serializable;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* Top level structure in an SVG tree.
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class SVGDiagram implements Serializable
|
||||
{
|
||||
public static final long serialVersionUID = 0;
|
||||
|
||||
//Indexes elements within this SVG diagram
|
||||
final HashMap<String, SVGElement> idMap = new HashMap<String, SVGElement>();
|
||||
|
||||
SVGRoot root;
|
||||
final SVGUniverse universe;
|
||||
private JComponent renderTarget;
|
||||
|
||||
/**
|
||||
* This is used by the SVGRoot to determine the width of the
|
||||
*/
|
||||
private Rectangle deviceViewport = new Rectangle(100, 100);
|
||||
|
||||
/**
|
||||
* If true, no attempt will be made to discard geometry based on it being
|
||||
* out of bounds. This trades potentially drawing many out of bounds
|
||||
* shapes with having to recalculate bounding boxes every animation iteration.
|
||||
*/
|
||||
protected boolean ignoreClipHeuristic = false;
|
||||
|
||||
/**
|
||||
* URL which uniquely identifies this document
|
||||
*/
|
||||
// final URI docRoot;
|
||||
|
||||
/**
|
||||
* URI that uniquely identifies this document. Also used to resolve
|
||||
* relative urls. Default base for document.
|
||||
*/
|
||||
final URI xmlBase;
|
||||
|
||||
/**
|
||||
* Creates a new instance of SVGDiagram
|
||||
* @param xmlBase
|
||||
* @param universe
|
||||
*/
|
||||
public SVGDiagram(URI xmlBase, SVGUniverse universe)
|
||||
{
|
||||
this.universe = universe;
|
||||
// this.docRoot = docRoot;
|
||||
this.xmlBase = xmlBase;
|
||||
}
|
||||
|
||||
JComponent getCurrentRenderTarget()
|
||||
{
|
||||
return renderTarget;
|
||||
}
|
||||
|
||||
public void render(JComponent c, Graphics2D g) throws SVGException
|
||||
{
|
||||
renderTarget = c;
|
||||
root.renderToViewport(g);
|
||||
renderTarget = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws this diagram to the passed graphics context
|
||||
* @param g
|
||||
* @throws SVGException
|
||||
*/
|
||||
public void render(Graphics2D g) throws SVGException
|
||||
{
|
||||
render(null, g);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches thorough the scene graph for all RenderableElements that have
|
||||
* shapes that contain the passed point.
|
||||
*
|
||||
* For every shape which contains the pick point, a List containing the
|
||||
* path to the node is added to the return list. That is, the result of
|
||||
* SVGElement.getPath() is added for each entry.
|
||||
*
|
||||
* @param point
|
||||
* @param retVec
|
||||
* @return the passed in list
|
||||
* @throws SVGException
|
||||
*/
|
||||
public List<List<SVGElement>> pick(Point2D point, List<List<SVGElement>> retVec) throws SVGException
|
||||
{
|
||||
return pick(point, false, retVec);
|
||||
}
|
||||
|
||||
public List<List<SVGElement>> pick(Point2D point, boolean boundingBox, List<List<SVGElement>> retVec) throws SVGException
|
||||
{
|
||||
if (retVec == null)
|
||||
{
|
||||
retVec = new ArrayList<List<SVGElement>>();
|
||||
}
|
||||
|
||||
root.pick(point, boundingBox, retVec);
|
||||
|
||||
return retVec;
|
||||
}
|
||||
|
||||
public List<List<SVGElement>> pick(Rectangle2D pickArea, List<List<SVGElement>> retVec) throws SVGException
|
||||
{
|
||||
return pick(pickArea, false, retVec);
|
||||
}
|
||||
|
||||
public List<List<SVGElement>> pick(Rectangle2D pickArea, boolean boundingBox, List<List<SVGElement>> retVec) throws SVGException
|
||||
{
|
||||
if (retVec == null)
|
||||
{
|
||||
retVec = new ArrayList<List<SVGElement>>();
|
||||
}
|
||||
|
||||
root.pick(pickArea, new AffineTransform(), boundingBox, retVec);
|
||||
|
||||
return retVec;
|
||||
}
|
||||
|
||||
public SVGUniverse getUniverse()
|
||||
{
|
||||
return universe;
|
||||
}
|
||||
|
||||
public URI getXMLBase()
|
||||
{
|
||||
return xmlBase;
|
||||
}
|
||||
|
||||
// public URL getDocRoot()
|
||||
// {
|
||||
// return docRoot;
|
||||
// }
|
||||
|
||||
public float getWidth()
|
||||
{
|
||||
if (root == null) return 0;
|
||||
return root.getDeviceWidth();
|
||||
}
|
||||
|
||||
public float getHeight()
|
||||
{
|
||||
if (root == null) return 0;
|
||||
return root.getDeviceHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the viewing rectangle of this diagram in device coordinates.
|
||||
* @param rect
|
||||
* @return
|
||||
*/
|
||||
public Rectangle2D getViewRect(Rectangle2D rect)
|
||||
{
|
||||
if (root != null) return root.getDeviceRect(rect);
|
||||
return rect;
|
||||
}
|
||||
|
||||
public Rectangle2D getViewRect()
|
||||
{
|
||||
return getViewRect(new Rectangle2D.Double());
|
||||
}
|
||||
|
||||
public SVGElement getElement(String name)
|
||||
{
|
||||
return (SVGElement)idMap.get(name);
|
||||
}
|
||||
|
||||
public void setElement(String name, SVGElement node)
|
||||
{
|
||||
idMap.put(name, node);
|
||||
}
|
||||
|
||||
public void removeElement(String name)
|
||||
{
|
||||
idMap.remove(name);
|
||||
}
|
||||
|
||||
public SVGRoot getRoot()
|
||||
{
|
||||
return root;
|
||||
}
|
||||
|
||||
public void setRoot(SVGRoot root)
|
||||
{
|
||||
this.root = root;
|
||||
root.setDiagram(this);
|
||||
}
|
||||
|
||||
public boolean ignoringClipHeuristic() { return ignoreClipHeuristic; }
|
||||
|
||||
public void setIgnoringClipHeuristic(boolean ignoreClipHeuristic) { this.ignoreClipHeuristic = ignoreClipHeuristic; }
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event.
|
||||
* Ie, all attributes with track information.
|
||||
* @param curTime
|
||||
* @throws SVGException
|
||||
*/
|
||||
public void updateTime(double curTime) throws SVGException
|
||||
{
|
||||
if (root == null) return;
|
||||
root.updateTime(curTime);
|
||||
}
|
||||
|
||||
public Rectangle getDeviceViewport()
|
||||
{
|
||||
return deviceViewport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the dimensions of the device being rendered into. This is used by
|
||||
* SVGRoot when its x, y, width or height parameters are specified as
|
||||
* percentages.
|
||||
* @param deviceViewport
|
||||
*/
|
||||
public void setDeviceViewport(Rectangle deviceViewport)
|
||||
{
|
||||
this.deviceViewport.setBounds(deviceViewport);
|
||||
if (root != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
root.build();
|
||||
} catch (SVGException ex)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not build document", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<Events>
|
||||
<EventHandler event="componentResized" listener="java.awt.event.ComponentListener" parameters="java.awt.event.ComponentEvent" handler="formComponentResized"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||
</Form>
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* 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 20, 2004, 12:29 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class SVGDisplayPanel extends javax.swing.JPanel implements Scrollable
|
||||
{
|
||||
public static final long serialVersionUID = 1;
|
||||
|
||||
SVGDiagram diagram = null;
|
||||
float scale = 1f;
|
||||
Color bgColor = null;
|
||||
|
||||
/** Creates new form SVGDisplayPanel */
|
||||
public SVGDisplayPanel()
|
||||
{
|
||||
initComponents();
|
||||
}
|
||||
|
||||
public SVGDiagram getDiagram()
|
||||
{
|
||||
return diagram;
|
||||
}
|
||||
|
||||
public void setDiagram(SVGDiagram diagram)
|
||||
{
|
||||
this.diagram = diagram;
|
||||
diagram.setDeviceViewport(getBounds());
|
||||
|
||||
setDimension();
|
||||
}
|
||||
|
||||
public void setScale(float scale)
|
||||
{
|
||||
this.scale = scale;
|
||||
setDimension();
|
||||
}
|
||||
|
||||
public void setBgColor(Color col)
|
||||
{
|
||||
bgColor = col;
|
||||
}
|
||||
|
||||
private void setDimension()
|
||||
{
|
||||
if (diagram == null)
|
||||
{
|
||||
setPreferredSize(new Dimension(1, 1));
|
||||
revalidate();
|
||||
return;
|
||||
}
|
||||
|
||||
final Rectangle2D.Float rect = new Rectangle2D.Float();
|
||||
diagram.getViewRect(rect);
|
||||
|
||||
int w = (int)(rect.width * scale);
|
||||
int h = (int)(rect.height * scale);
|
||||
|
||||
setPreferredSize(new Dimension(w, h));
|
||||
revalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update this image to reflect the passed time
|
||||
* @param curTime
|
||||
* @throws SVGException
|
||||
*/
|
||||
public void updateTime(double curTime) throws SVGException
|
||||
{
|
||||
if (diagram == null) return;
|
||||
|
||||
diagram.updateTime(curTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics gg)
|
||||
{
|
||||
Graphics2D g = (Graphics2D)gg;
|
||||
|
||||
if (bgColor != null)
|
||||
{
|
||||
Dimension dim = getSize();
|
||||
g.setColor(bgColor);
|
||||
g.fillRect(0, 0, dim.width, dim.height);
|
||||
}
|
||||
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
||||
if (diagram != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
diagram.render(g);
|
||||
}
|
||||
catch (SVGException e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not render diagram", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
|
||||
private void initComponents()
|
||||
{
|
||||
|
||||
setLayout(new java.awt.BorderLayout());
|
||||
|
||||
addComponentListener(new java.awt.event.ComponentAdapter()
|
||||
{
|
||||
@Override
|
||||
public void componentResized(java.awt.event.ComponentEvent evt)
|
||||
{
|
||||
formComponentResized(evt);
|
||||
}
|
||||
});
|
||||
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void formComponentResized(java.awt.event.ComponentEvent evt)//GEN-FIRST:event_formComponentResized
|
||||
{//GEN-HEADEREND:event_formComponentResized
|
||||
if (diagram != null)
|
||||
{
|
||||
diagram.setDeviceViewport(getBounds());
|
||||
setDimension();
|
||||
}
|
||||
|
||||
}//GEN-LAST:event_formComponentResized
|
||||
|
||||
public Dimension getPreferredScrollableViewportSize()
|
||||
{
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction)
|
||||
{
|
||||
if (orientation == SwingConstants.HORIZONTAL)
|
||||
{
|
||||
return visibleRect.width;
|
||||
}
|
||||
else return visibleRect.height;
|
||||
}
|
||||
|
||||
public boolean getScrollableTracksViewportHeight()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean getScrollableTracksViewportWidth()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction)
|
||||
{
|
||||
return getScrollableBlockIncrement(visibleRect, orientation, direction) / 16;
|
||||
}
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
}
|
863
graphics-svg/src/main/java/org/xbib/graphics/svg/SVGElement.java
Normal file
863
graphics-svg/src/main/java/org/xbib/graphics/svg/SVGElement.java
Normal file
|
@ -0,0 +1,863 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 1:59 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.animation.AnimationElement;
|
||||
import org.xbib.graphics.svg.animation.TrackBase;
|
||||
import org.xbib.graphics.svg.animation.TrackManager;
|
||||
import org.xbib.graphics.svg.pathcmd.BuildHistory;
|
||||
import org.xbib.graphics.svg.pathcmd.PathCommand;
|
||||
import org.xbib.graphics.svg.pathcmd.PathParser;
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import org.xbib.graphics.svg.xml.StyleSheet;
|
||||
import org.xbib.graphics.svg.xml.XMLParseUtil;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.io.Serializable;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
abstract public class SVGElement implements Serializable
|
||||
{
|
||||
|
||||
public static final long serialVersionUID = 0;
|
||||
public static final String SVG_NS = "http://www.w3.org/2000/svg";
|
||||
protected SVGElement parent = null;
|
||||
protected final ArrayList<SVGElement> children = new ArrayList<SVGElement>();
|
||||
protected String id = null;
|
||||
/**
|
||||
* CSS class. Used for applying style sheet information.
|
||||
*/
|
||||
protected String cssClass = null;
|
||||
/**
|
||||
* Styles defined for this elemnt via the <b>style</b> attribute.
|
||||
*/
|
||||
protected final HashMap<String, StyleAttribute> inlineStyles = new HashMap<String, StyleAttribute>();
|
||||
/**
|
||||
* Presentation attributes set for this element. Ie, any attribute other
|
||||
* than the <b>style</b> attribute.
|
||||
*/
|
||||
protected final HashMap<String, StyleAttribute> presAttribs = new HashMap<String, StyleAttribute>();
|
||||
/**
|
||||
* This element may override the URI we resolve against with an xml:base
|
||||
* attribute. If so, a copy is placed here. Otherwise, we defer to our
|
||||
* parent for the reolution base
|
||||
*/
|
||||
protected URI xmlBase = null;
|
||||
/**
|
||||
* The diagram this element belongs to
|
||||
*/
|
||||
protected SVGDiagram diagram;
|
||||
/**
|
||||
* Link to the universe we reside in
|
||||
*/
|
||||
protected final TrackManager trackManager = new TrackManager();
|
||||
boolean dirty = true;
|
||||
|
||||
/**
|
||||
* Creates a new instance of SVGElement
|
||||
*/
|
||||
public SVGElement()
|
||||
{
|
||||
this(null, null, null);
|
||||
}
|
||||
|
||||
public SVGElement(String id, SVGElement parent)
|
||||
{
|
||||
this(id, null, parent);
|
||||
}
|
||||
|
||||
public SVGElement(String id, String cssClass, SVGElement parent)
|
||||
{
|
||||
this.id = id;
|
||||
this.cssClass = cssClass;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
abstract public String getTagName();
|
||||
|
||||
public SVGElement getParent()
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
void setParent(SVGElement parent)
|
||||
{
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param retVec
|
||||
* @return an ordered list of nodes from the root of the tree to this node
|
||||
*/
|
||||
public List<SVGElement> getPath(List<SVGElement> retVec)
|
||||
{
|
||||
if (retVec == null)
|
||||
{
|
||||
retVec = new ArrayList<SVGElement>();
|
||||
}
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
parent.getPath(retVec);
|
||||
}
|
||||
retVec.add(this);
|
||||
|
||||
return retVec;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param retVec - A list to add all children to. If null, a new list is
|
||||
* created and children of this group are added.
|
||||
*
|
||||
* @return The list containing the children of this group
|
||||
*/
|
||||
public List<SVGElement> getChildren(List<SVGElement> retVec)
|
||||
{
|
||||
if (retVec == null)
|
||||
{
|
||||
retVec = new ArrayList<SVGElement>();
|
||||
}
|
||||
|
||||
retVec.addAll(children);
|
||||
|
||||
return retVec;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id - Id of svg element to return
|
||||
* @return the child of the given id, or null if no such child exists.
|
||||
*/
|
||||
public SVGElement getChild(String id)
|
||||
{
|
||||
for (SVGElement ele : children) {
|
||||
String eleId = ele.getId();
|
||||
if (eleId != null && eleId.equals(id))
|
||||
{
|
||||
return ele;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches children for given element. If found, returns index of child.
|
||||
* Otherwise returns -1.
|
||||
* @param child
|
||||
* @return index of child
|
||||
*/
|
||||
public int indexOfChild(SVGElement child)
|
||||
{
|
||||
return children.indexOf(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps 2 elements in children.
|
||||
*
|
||||
* @param i index of first child
|
||||
* @param j index of second child
|
||||
* @throws SVGException
|
||||
*/
|
||||
public void swapChildren(int i, int j) throws SVGException
|
||||
{
|
||||
if ((children == null) || (i < 0) || (i >= children.size()) || (j < 0) || (j >= children.size()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SVGElement temp = children.get(i);
|
||||
children.set(i, children.get(j));
|
||||
children.set(j, temp);
|
||||
build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during SAX load process to notify that this tag has begun the
|
||||
* process of being loaded
|
||||
*
|
||||
* @param attrs - Attributes of this tag
|
||||
* @param helper - An object passed to all SVG elements involved in this
|
||||
* build process to aid in sharing information.
|
||||
* @param parent
|
||||
* @throws org.xml.sax.SAXException
|
||||
*/
|
||||
public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) throws SAXException
|
||||
{
|
||||
//Set identification info
|
||||
this.parent = parent;
|
||||
this.diagram = helper.diagram;
|
||||
|
||||
this.id = attrs.getValue("id");
|
||||
if (this.id != null && !this.id.equals(""))
|
||||
{
|
||||
this.id = this.id.intern();
|
||||
diagram.setElement(this.id, this);
|
||||
}
|
||||
|
||||
String className = attrs.getValue("class");
|
||||
this.cssClass = (className == null || className.equals("")) ? null : className.intern();
|
||||
//docRoot = helper.docRoot;
|
||||
//universe = helper.universe;
|
||||
|
||||
//Parse style string, if any
|
||||
String style = attrs.getValue("style");
|
||||
if (style != null)
|
||||
{
|
||||
HashMap<?, ?> map = XMLParseUtil.parseStyle(style, inlineStyles);
|
||||
}
|
||||
|
||||
String base = attrs.getValue("xml:base");
|
||||
if (base != null && !base.equals(""))
|
||||
{
|
||||
try
|
||||
{
|
||||
xmlBase = new URI(base);
|
||||
} catch (Exception e)
|
||||
{
|
||||
throw new SAXException(e);
|
||||
}
|
||||
}
|
||||
|
||||
//Place all other attributes into the presentation attribute list
|
||||
int numAttrs = attrs.getLength();
|
||||
for (int i = 0; i < numAttrs; i++)
|
||||
{
|
||||
String name = attrs.getQName(i).intern();
|
||||
String value = attrs.getValue(i);
|
||||
|
||||
presAttribs.put(name, new StyleAttribute(name, value == null ? null : value.intern()));
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAttribute(String name, int attribType)
|
||||
{
|
||||
switch (attribType)
|
||||
{
|
||||
case AnimationElement.AT_CSS:
|
||||
inlineStyles.remove(name);
|
||||
return;
|
||||
case AnimationElement.AT_XML:
|
||||
presAttribs.remove(name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void addAttribute(String name, int attribType, String value) throws SVGElementException
|
||||
{
|
||||
if (hasAttribute(name, attribType))
|
||||
{
|
||||
throw new SVGElementException(this, "Attribute " + name + "(" + AnimationElement.animationElementToString(attribType) + ") already exists");
|
||||
}
|
||||
|
||||
//Alter layout for id attribute
|
||||
if ("id".equals(name))
|
||||
{
|
||||
if (diagram != null)
|
||||
{
|
||||
diagram.removeElement(id);
|
||||
diagram.setElement(value, this);
|
||||
}
|
||||
this.id = value;
|
||||
}
|
||||
|
||||
switch (attribType)
|
||||
{
|
||||
case AnimationElement.AT_CSS:
|
||||
inlineStyles.put(name, new StyleAttribute(name, value));
|
||||
return;
|
||||
case AnimationElement.AT_XML:
|
||||
presAttribs.put(name, new StyleAttribute(name, value));
|
||||
return;
|
||||
}
|
||||
|
||||
throw new SVGElementException(this, "Invalid attribute type " + attribType);
|
||||
}
|
||||
|
||||
public boolean hasAttribute(String name, int attribType) throws SVGElementException
|
||||
{
|
||||
switch (attribType)
|
||||
{
|
||||
case AnimationElement.AT_CSS:
|
||||
return inlineStyles.containsKey(name);
|
||||
case AnimationElement.AT_XML:
|
||||
return presAttribs.containsKey(name);
|
||||
case AnimationElement.AT_AUTO:
|
||||
return inlineStyles.containsKey(name) || presAttribs.containsKey(name);
|
||||
}
|
||||
|
||||
throw new SVGElementException(this, "Invalid attribute type " + attribType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a set of Strings that correspond to CSS attributes on this element
|
||||
*/
|
||||
public Set<String> getInlineAttributes()
|
||||
{
|
||||
return inlineStyles.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a set of Strings that correspond to XML attributes on this element
|
||||
*/
|
||||
public Set<String> getPresentationAttributes()
|
||||
{
|
||||
return presAttribs.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the start element but before the end element to indicate
|
||||
* each child tag that has been processed
|
||||
* @param helper
|
||||
* @param child
|
||||
* @throws SVGElementException
|
||||
*/
|
||||
public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
|
||||
{
|
||||
children.add(child);
|
||||
child.parent = this;
|
||||
child.setDiagram(diagram);
|
||||
|
||||
//Add info to track if we've scanned animation element
|
||||
if (child instanceof AnimationElement)
|
||||
{
|
||||
trackManager.addTrackElement((AnimationElement) child);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setDiagram(SVGDiagram diagram)
|
||||
{
|
||||
this.diagram = diagram;
|
||||
diagram.setElement(id, this);
|
||||
for (SVGElement ele : children) {
|
||||
ele.setDiagram(diagram);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeChild(SVGElement child) throws SVGElementException
|
||||
{
|
||||
if (!children.contains(child))
|
||||
{
|
||||
throw new SVGElementException(this, "Element does not contain child " + child);
|
||||
}
|
||||
|
||||
children.remove(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during load process to add text scanned within a tag
|
||||
* @param helper
|
||||
* @param text
|
||||
*/
|
||||
public void loaderAddText(SVGLoaderHelper helper, String text)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to indicate that this tag and the tags it contains have been
|
||||
* completely processed, and that it should finish any load processes.
|
||||
* @param helper
|
||||
* @throws SVGParseException
|
||||
*/
|
||||
public void loaderEndElement(SVGLoaderHelper helper) throws SVGParseException
|
||||
{
|
||||
// try
|
||||
// {
|
||||
// build();
|
||||
// }
|
||||
// catch (SVGException se)
|
||||
// {
|
||||
// throw new SVGParseException(se);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by internal processes to rebuild the geometry of this node from
|
||||
* it's presentation attributes, style attributes and animated tracks.
|
||||
* @throws SVGException
|
||||
*/
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("id")))
|
||||
{
|
||||
String newId = sty.getStringValue();
|
||||
if (!newId.equals(id))
|
||||
{
|
||||
diagram.removeElement(id);
|
||||
id = newId;
|
||||
diagram.setElement(this.id, this);
|
||||
}
|
||||
}
|
||||
if (getPres(sty.setName("class")))
|
||||
{
|
||||
cssClass = sty.getStringValue();
|
||||
}
|
||||
if (getPres(sty.setName("xml:base")))
|
||||
{
|
||||
xmlBase = sty.getURIValue();
|
||||
}
|
||||
|
||||
//Build children
|
||||
for (int i = 0; i < children.size(); ++i)
|
||||
{
|
||||
SVGElement ele = (SVGElement) children.get(i);
|
||||
ele.build();
|
||||
}
|
||||
}
|
||||
|
||||
public URI getXMLBase()
|
||||
{
|
||||
return xmlBase != null ? xmlBase
|
||||
: (parent != null ? parent.getXMLBase() : diagram.getXMLBase());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id assigned to this node. Null if no id explicitly set.
|
||||
*/
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
LinkedList<SVGElement> contexts = new LinkedList<SVGElement>();
|
||||
|
||||
/**
|
||||
* Hack to allow nodes to temporarily change their parents. The Use tag will
|
||||
* need this so it can alter the attributes that a particular node uses.
|
||||
* @param context
|
||||
*/
|
||||
protected void pushParentContext(SVGElement context)
|
||||
{
|
||||
contexts.addLast(context);
|
||||
}
|
||||
|
||||
protected SVGElement popParentContext()
|
||||
{
|
||||
return (SVGElement) contexts.removeLast();
|
||||
}
|
||||
|
||||
protected SVGElement getParentContext()
|
||||
{
|
||||
return contexts.isEmpty() ? null : (SVGElement) contexts.getLast();
|
||||
}
|
||||
|
||||
public SVGRoot getRoot()
|
||||
{
|
||||
return parent == null ? null : parent.getRoot();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the named style attribute. Checks for inline styles first, then
|
||||
* internal and extranal style sheets, and finally checks for presentation
|
||||
* attributes.
|
||||
* @param styleName - Name of attribute to return
|
||||
* @param recursive - If true and this object does not contain the
|
||||
* named style attribute, checks attributes of parents abck to root until
|
||||
* one found.
|
||||
*/
|
||||
public boolean getStyle(StyleAttribute attrib) throws SVGException
|
||||
{
|
||||
return getStyle(attrib, true);
|
||||
}
|
||||
|
||||
public void setAttribute(String name, int attribType, String value) throws SVGElementException
|
||||
{
|
||||
StyleAttribute styAttr;
|
||||
|
||||
|
||||
switch (attribType)
|
||||
{
|
||||
case AnimationElement.AT_CSS:
|
||||
{
|
||||
styAttr = (StyleAttribute) inlineStyles.get(name);
|
||||
break;
|
||||
}
|
||||
case AnimationElement.AT_XML:
|
||||
{
|
||||
styAttr = (StyleAttribute) presAttribs.get(name);
|
||||
break;
|
||||
}
|
||||
case AnimationElement.AT_AUTO:
|
||||
{
|
||||
styAttr = (StyleAttribute) inlineStyles.get(name);
|
||||
|
||||
if (styAttr == null)
|
||||
{
|
||||
styAttr = (StyleAttribute) presAttribs.get(name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new SVGElementException(this, "Invalid attribute type " + attribType);
|
||||
}
|
||||
|
||||
if (styAttr == null)
|
||||
{
|
||||
throw new SVGElementException(this, "Could not find attribute " + name + "(" + AnimationElement.animationElementToString(attribType) + "). Make sure to create attribute before setting it.");
|
||||
}
|
||||
|
||||
//Alter layout for relevant attributes
|
||||
if ("id".equals(styAttr.getName()))
|
||||
{
|
||||
if (diagram != null)
|
||||
{
|
||||
diagram.removeElement(this.id);
|
||||
diagram.setElement(value, this);
|
||||
}
|
||||
this.id = value;
|
||||
}
|
||||
|
||||
styAttr.setStringValue(value);
|
||||
}
|
||||
|
||||
public boolean getStyle(StyleAttribute attrib, boolean recursive) throws SVGException
|
||||
{
|
||||
return getStyle(attrib, recursive, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the current style into the passed style attribute. Checks for
|
||||
* inline styles first, then internal and extranal style sheets, and finally
|
||||
* checks for presentation attributes. Recursively checks parents.
|
||||
*
|
||||
* @param attrib - Attribute to write style data to. Must have it's name set
|
||||
* to the name of the style being queried.
|
||||
* @param recursive - If true and this object does not contain the named
|
||||
* style attribute, checks attributes of parents back to root until one
|
||||
* found.
|
||||
* @param evalAnimation
|
||||
* @return
|
||||
*/
|
||||
public boolean getStyle(StyleAttribute attrib, boolean recursive, boolean evalAnimation)
|
||||
throws SVGException
|
||||
{
|
||||
String styName = attrib.getName();
|
||||
|
||||
//Check for local inline styles
|
||||
StyleAttribute styAttr = (StyleAttribute)inlineStyles.get(styName);
|
||||
|
||||
attrib.setStringValue(styAttr == null ? "" : styAttr.getStringValue());
|
||||
|
||||
//Evalutate corresponding track, if one exists
|
||||
if (evalAnimation)
|
||||
{
|
||||
TrackBase track = trackManager.getTrack(styName, AnimationElement.AT_CSS);
|
||||
if (track != null)
|
||||
{
|
||||
track.getValue(attrib, diagram.getUniverse().getCurTime());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//Return if we've found a non animated style
|
||||
if (styAttr != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//Check for presentation attribute
|
||||
StyleAttribute presAttr = (StyleAttribute)presAttribs.get(styName);
|
||||
|
||||
attrib.setStringValue(presAttr == null ? "" : presAttr.getStringValue());
|
||||
|
||||
//Evalutate corresponding track, if one exists
|
||||
if (evalAnimation)
|
||||
{
|
||||
TrackBase track = trackManager.getTrack(styName, AnimationElement.AT_XML);
|
||||
if (track != null)
|
||||
{
|
||||
track.getValue(attrib, diagram.getUniverse().getCurTime());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//Return if we've found a presentation attribute instead
|
||||
if (presAttr != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//Check for style sheet
|
||||
SVGRoot root = getRoot();
|
||||
if (root != null)
|
||||
{
|
||||
StyleSheet ss = root.getStyleSheet();
|
||||
if (ss != null)
|
||||
{
|
||||
return ss.getStyle(attrib, getTagName(), cssClass);
|
||||
}
|
||||
}
|
||||
|
||||
//If we're recursive, check parents
|
||||
if (recursive)
|
||||
{
|
||||
SVGElement parentContext = getParentContext();
|
||||
if (parentContext != null)
|
||||
{
|
||||
return parentContext.getStyle(attrib, true);
|
||||
}
|
||||
if (parent != null)
|
||||
{
|
||||
return parent.getStyle(attrib, true);
|
||||
}
|
||||
}
|
||||
|
||||
//Unsuccessful reading style attribute
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param styName
|
||||
* @return the raw style value of this attribute. Does not take the
|
||||
* presentation value or animation into consideration. Used by animations to
|
||||
* determine the base to animate from.
|
||||
*/
|
||||
public StyleAttribute getStyleAbsolute(String styName)
|
||||
{
|
||||
//Check for local inline styles
|
||||
return (StyleAttribute) inlineStyles.get(styName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the presentation attribute into the passed one.
|
||||
*
|
||||
* @param attrib
|
||||
* @return - True if attribute was read successfully
|
||||
* @throws SVGException
|
||||
*/
|
||||
public boolean getPres(StyleAttribute attrib) throws SVGException
|
||||
{
|
||||
String presName = attrib.getName();
|
||||
|
||||
//Make sure we have a corresponding presentation attribute
|
||||
StyleAttribute presAttr = (StyleAttribute) presAttribs.get(presName);
|
||||
|
||||
//Copy presentation value directly
|
||||
attrib.setStringValue(presAttr == null ? "" : presAttr.getStringValue());
|
||||
|
||||
//Evalutate corresponding track, if one exists
|
||||
TrackBase track = trackManager.getTrack(presName, AnimationElement.AT_XML);
|
||||
if (track != null)
|
||||
{
|
||||
track.getValue(attrib, diagram.getUniverse().getCurTime());
|
||||
return true;
|
||||
}
|
||||
|
||||
//Return if we found presentation attribute
|
||||
if (presAttr != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param styName
|
||||
* @return the raw presentation value of this attribute. Ignores any
|
||||
* modifications applied by style attributes or animation. Used by
|
||||
* animations to determine the starting point to animate from
|
||||
*/
|
||||
public StyleAttribute getPresAbsolute(String styName)
|
||||
{
|
||||
//Check for local inline styles
|
||||
return (StyleAttribute) presAttribs.get(styName);
|
||||
}
|
||||
|
||||
private static final Pattern TRANSFORM_PATTERN = Pattern.compile("\\w+\\([^)]*\\)");
|
||||
static protected AffineTransform parseTransform(String val) throws SVGException
|
||||
{
|
||||
final Matcher matchExpression = TRANSFORM_PATTERN.matcher("");
|
||||
|
||||
AffineTransform retXform = new AffineTransform();
|
||||
|
||||
matchExpression.reset(val);
|
||||
while (matchExpression.find())
|
||||
{
|
||||
retXform.concatenate(parseSingleTransform(matchExpression.group()));
|
||||
}
|
||||
|
||||
return retXform;
|
||||
}
|
||||
|
||||
private static final Pattern WORD_PATTERN = Pattern.compile("([a-zA-Z]+|-?\\d+(\\.\\d+)?([eE]-?\\d+)?|-?\\.\\d+([eE]-?\\d+)?)");
|
||||
static public AffineTransform parseSingleTransform(String val) throws SVGException
|
||||
{
|
||||
final Matcher matchWord = WORD_PATTERN.matcher("");
|
||||
|
||||
AffineTransform retXform = new AffineTransform();
|
||||
|
||||
matchWord.reset(val);
|
||||
if (!matchWord.find())
|
||||
{
|
||||
//Return identity transformation if no data present (eg, empty string)
|
||||
return retXform;
|
||||
}
|
||||
|
||||
String function = matchWord.group().toLowerCase();
|
||||
|
||||
LinkedList<String> termList = new LinkedList<String>();
|
||||
while (matchWord.find())
|
||||
{
|
||||
termList.add(matchWord.group());
|
||||
}
|
||||
|
||||
|
||||
double[] terms = new double[termList.size()];
|
||||
Iterator<String> it = termList.iterator();
|
||||
int count = 0;
|
||||
while (it.hasNext())
|
||||
{
|
||||
terms[count++] = XMLParseUtil.parseDouble(it.next());
|
||||
}
|
||||
|
||||
//Calculate transformation
|
||||
if (function.equals("matrix"))
|
||||
{
|
||||
retXform.setTransform(terms[0], terms[1], terms[2], terms[3], terms[4], terms[5]);
|
||||
} else if (function.equals("translate"))
|
||||
{
|
||||
if (terms.length == 1)
|
||||
{
|
||||
retXform.setToTranslation(terms[0], 0);
|
||||
} else
|
||||
{
|
||||
retXform.setToTranslation(terms[0], terms[1]);
|
||||
}
|
||||
} else if (function.equals("scale"))
|
||||
{
|
||||
if (terms.length > 1)
|
||||
{
|
||||
retXform.setToScale(terms[0], terms[1]);
|
||||
} else
|
||||
{
|
||||
retXform.setToScale(terms[0], terms[0]);
|
||||
}
|
||||
} else if (function.equals("rotate"))
|
||||
{
|
||||
if (terms.length > 2)
|
||||
{
|
||||
retXform.setToRotation(Math.toRadians(terms[0]), terms[1], terms[2]);
|
||||
} else
|
||||
{
|
||||
retXform.setToRotation(Math.toRadians(terms[0]));
|
||||
}
|
||||
} else if (function.equals("skewx"))
|
||||
{
|
||||
retXform.setToShear(Math.toRadians(terms[0]), 0.0);
|
||||
} else if (function.equals("skewy"))
|
||||
{
|
||||
retXform.setToShear(0.0, Math.toRadians(terms[0]));
|
||||
} else
|
||||
{
|
||||
throw new SVGException("Unknown transform type");
|
||||
}
|
||||
|
||||
return retXform;
|
||||
}
|
||||
|
||||
static protected PathCommand[] parsePathList(String list)
|
||||
{
|
||||
return new PathParser(list).parsePathCommand();
|
||||
}
|
||||
|
||||
static protected GeneralPath buildPath(String text, int windingRule)
|
||||
{
|
||||
PathCommand[] commands = parsePathList(text);
|
||||
|
||||
int numKnots = 2;
|
||||
for (int i = 0; i < commands.length; i++)
|
||||
{
|
||||
numKnots += commands[i].getNumKnotsAdded();
|
||||
}
|
||||
|
||||
|
||||
GeneralPath path = new GeneralPath(windingRule, numKnots);
|
||||
|
||||
BuildHistory hist = new BuildHistory();
|
||||
|
||||
for (int i = 0; i < commands.length; i++)
|
||||
{
|
||||
PathCommand cmd = commands[i];
|
||||
cmd.appendPath(path, hist);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @param curTime
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
* @throws SVGException
|
||||
*/
|
||||
abstract public boolean updateTime(double curTime) throws SVGException;
|
||||
|
||||
public int getNumChildren()
|
||||
{
|
||||
return children.size();
|
||||
}
|
||||
|
||||
public SVGElement getChild(int i)
|
||||
{
|
||||
return (SVGElement) children.get(i);
|
||||
}
|
||||
|
||||
public double lerp(double t0, double t1, double alpha)
|
||||
{
|
||||
return (1 - alpha) * t0 + alpha * t1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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 SVGElementException extends SVGException
|
||||
{
|
||||
public static final long serialVersionUID = 0;
|
||||
|
||||
private final SVGElement element;
|
||||
|
||||
/**
|
||||
* Creates a new instance of <code>SVGException</code> without detail message.
|
||||
* @param element
|
||||
*/
|
||||
public SVGElementException(SVGElement element)
|
||||
{
|
||||
this(element, null, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>SVGException</code> 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;
|
||||
}
|
||||
}
|
|
@ -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 <code>SVGException</code> without detail message.
|
||||
*/
|
||||
public SVGException()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>SVGException</code> 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);
|
||||
}
|
||||
}
|
308
graphics-svg/src/main/java/org/xbib/graphics/svg/SVGLoader.java
Normal file
308
graphics-svg/src/main/java/org/xbib/graphics/svg/SVGLoader.java
Normal file
|
@ -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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class SVGLoader extends DefaultHandler
|
||||
{
|
||||
final HashMap<String, Class<?>> nodeClasses = new HashMap<String, Class<?>>();
|
||||
//final HashMap attribClasses = new HashMap();
|
||||
final LinkedList<SVGElement> buildStack = new LinkedList<SVGElement>();
|
||||
|
||||
final HashSet<String> ignoreClasses = new HashSet<String>();
|
||||
|
||||
final SVGLoaderHelper helper;
|
||||
|
||||
/**
|
||||
* The diagram that represents the base of this SVG document we're loading.
|
||||
* Will be augmented to include node indexing info and other useful stuff.
|
||||
*/
|
||||
final SVGDiagram diagram;
|
||||
|
||||
// SVGElement loadRoot;
|
||||
|
||||
//Used to keep track of document elements that are not part of the SVG namespace
|
||||
int skipNonSVGTagDepth = 0;
|
||||
int indent = 0;
|
||||
|
||||
final boolean verbose;
|
||||
|
||||
/**
|
||||
* Creates a new instance of SVGLoader
|
||||
* @param xmlBase
|
||||
* @param universe
|
||||
*/
|
||||
public SVGLoader(URI xmlBase, SVGUniverse universe)
|
||||
{
|
||||
this(xmlBase, universe, false);
|
||||
}
|
||||
|
||||
public SVGLoader(URI xmlBase, SVGUniverse universe, boolean verbose)
|
||||
{
|
||||
this.verbose = verbose;
|
||||
|
||||
diagram = new SVGDiagram(xmlBase, universe);
|
||||
|
||||
//Compile a list of important builder classes
|
||||
nodeClasses.put("a", A.class);
|
||||
nodeClasses.put("animate", Animate.class);
|
||||
nodeClasses.put("animatecolor", AnimateColor.class);
|
||||
nodeClasses.put("animatemotion", AnimateMotion.class);
|
||||
nodeClasses.put("animatetransform", AnimateTransform.class);
|
||||
nodeClasses.put("circle", Circle.class);
|
||||
nodeClasses.put("clippath", ClipPath.class);
|
||||
nodeClasses.put("defs", Defs.class);
|
||||
nodeClasses.put("desc", Desc.class);
|
||||
nodeClasses.put("ellipse", Ellipse.class);
|
||||
nodeClasses.put("filter", Filter.class);
|
||||
nodeClasses.put(FeGaussianBlur.TAG_NAME, FeGaussianBlur.class);
|
||||
nodeClasses.put("font", Font.class);
|
||||
nodeClasses.put("font-face", FontFace.class);
|
||||
nodeClasses.put("g", Group.class);
|
||||
nodeClasses.put("glyph", Glyph.class);
|
||||
nodeClasses.put("hkern", Hkern.class);
|
||||
nodeClasses.put("image", ImageSVG.class);
|
||||
nodeClasses.put("line", Line.class);
|
||||
nodeClasses.put("lineargradient", LinearGradient.class);
|
||||
nodeClasses.put("marker", Marker.class);
|
||||
nodeClasses.put("mask", Mask.class);
|
||||
nodeClasses.put("metadata", Metadata.class);
|
||||
nodeClasses.put("missing-glyph", MissingGlyph.class);
|
||||
nodeClasses.put("path", Path.class);
|
||||
nodeClasses.put("pattern", PatternSVG.class);
|
||||
nodeClasses.put("polygon", Polygon.class);
|
||||
nodeClasses.put("polyline", Polyline.class);
|
||||
nodeClasses.put("radialgradient", RadialGradient.class);
|
||||
nodeClasses.put("rect", Rect.class);
|
||||
nodeClasses.put("set", SetSmil.class);
|
||||
nodeClasses.put("shape", ShapeElement.class);
|
||||
nodeClasses.put("stop", Stop.class);
|
||||
nodeClasses.put("style", Style.class);
|
||||
nodeClasses.put("svg", SVGRoot.class);
|
||||
nodeClasses.put("symbol", Symbol.class);
|
||||
nodeClasses.put("text", Text.class);
|
||||
nodeClasses.put("title", Title.class);
|
||||
nodeClasses.put("tspan", Tspan.class);
|
||||
nodeClasses.put("use", Use.class);
|
||||
|
||||
ignoreClasses.add("midpointstop");
|
||||
|
||||
//attribClasses.put("clip-path", StyleUrl.class);
|
||||
//attribClasses.put("color", StyleColor.class);
|
||||
|
||||
helper = new SVGLoaderHelper(xmlBase, universe, diagram);
|
||||
}
|
||||
|
||||
private String printIndent(int indent, String indentStrn)
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < indent; i++)
|
||||
{
|
||||
sb.append(indentStrn);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDocument() throws SAXException
|
||||
{
|
||||
// System.err.println("Start doc");
|
||||
|
||||
// buildStack.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endDocument() throws SAXException
|
||||
{
|
||||
// System.err.println("End doc");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String namespaceURI, String sName, String qName, Attributes attrs) throws SAXException
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
System.err.println(printIndent(indent, " ") + "Starting parse of tag " + sName+ ": " + namespaceURI);
|
||||
}
|
||||
indent++;
|
||||
|
||||
if (skipNonSVGTagDepth != 0 || (!namespaceURI.equals("") && !namespaceURI.equals(SVGElement.SVG_NS)))
|
||||
{
|
||||
skipNonSVGTagDepth++;
|
||||
return;
|
||||
}
|
||||
|
||||
sName = sName.toLowerCase();
|
||||
|
||||
//javax.swing.JOptionPane.showMessageDialog(null, sName);
|
||||
|
||||
Object obj = nodeClasses.get(sName);
|
||||
if (obj == null)
|
||||
{
|
||||
if (!ignoreClasses.contains(sName))
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
System.err.println("SVGLoader: Could not identify tag '" + sName + "'");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//Debug info tag depth
|
||||
//for (int i = 0; i < buildStack.size(); i++) System.err.print(" ");
|
||||
//System.err.println("+" + sName);
|
||||
|
||||
try {
|
||||
Class<?> cls = (Class<?>)obj;
|
||||
SVGElement svgEle = (SVGElement)cls.newInstance();
|
||||
|
||||
SVGElement parent = null;
|
||||
if (buildStack.size() != 0) parent = (SVGElement)buildStack.getLast();
|
||||
svgEle.loaderStartElement(helper, attrs, parent);
|
||||
|
||||
buildStack.addLast(svgEle);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not load", e);
|
||||
throw new SAXException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String namespaceURI, String sName, String qName)
|
||||
throws SAXException
|
||||
{
|
||||
indent--;
|
||||
if (verbose)
|
||||
{
|
||||
System.err.println(printIndent(indent, " ") + "Ending parse of tag " + sName+ ": " + namespaceURI);
|
||||
}
|
||||
|
||||
if (skipNonSVGTagDepth != 0)
|
||||
{
|
||||
skipNonSVGTagDepth--;
|
||||
return;
|
||||
}
|
||||
|
||||
sName = sName.toLowerCase();
|
||||
|
||||
Object obj = nodeClasses.get(sName);
|
||||
if (obj == null) return;
|
||||
|
||||
//Debug info tag depth
|
||||
//for (int i = 0; i < buildStack.size(); i++) System.err.print(" ");
|
||||
//System.err.println("-" + sName);
|
||||
|
||||
try {
|
||||
SVGElement svgEle = (SVGElement)buildStack.removeLast();
|
||||
|
||||
svgEle.loaderEndElement(helper);
|
||||
|
||||
SVGElement parent = null;
|
||||
if (buildStack.size() != 0)
|
||||
{
|
||||
parent = (SVGElement)buildStack.getLast();
|
||||
}
|
||||
//else loadRoot = (SVGElement)svgEle;
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
parent.loaderAddChild(helper, svgEle);
|
||||
}
|
||||
else
|
||||
{
|
||||
diagram.setRoot((SVGRoot)svgEle);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not parse", e);
|
||||
throw new SAXException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(char buf[], int offset, int len)
|
||||
throws SAXException
|
||||
{
|
||||
if (skipNonSVGTagDepth != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildStack.size() != 0)
|
||||
{
|
||||
SVGElement parent = (SVGElement)buildStack.getLast();
|
||||
String s = new String(buf, offset, len);
|
||||
parent.loaderAddText(helper, s);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processingInstruction(String target, String data)
|
||||
throws SAXException
|
||||
{
|
||||
//Check for external style sheet
|
||||
}
|
||||
|
||||
// public SVGElement getLoadRoot() { return loadRoot; }
|
||||
public SVGDiagram getLoadedDiagram() { return diagram; }
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package org.xbib.graphics.svg;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
public class SVGLoaderHelper
|
||||
{
|
||||
public final SVGUniverse universe;
|
||||
|
||||
public final SVGDiagram diagram;
|
||||
|
||||
public final URI xmlBase;
|
||||
|
||||
public SVGLoaderHelper(URI xmlBase, SVGUniverse universe, SVGDiagram diagram)
|
||||
{
|
||||
this.xmlBase = xmlBase;
|
||||
this.universe = universe;
|
||||
this.diagram = diagram;
|
||||
}
|
||||
|
||||
}
|
|
@ -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 SVGParseException extends java.lang.Exception
|
||||
{
|
||||
public static final long serialVersionUID = 0;
|
||||
|
||||
/**
|
||||
* Creates a new instance of <code>SVGException</code> without detail message.
|
||||
*/
|
||||
public SVGParseException()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>SVGException</code> 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);
|
||||
}
|
||||
}
|
496
graphics-svg/src/main/java/org/xbib/graphics/svg/SVGRoot.java
Normal file
496
graphics-svg/src/main/java/org/xbib/graphics/svg/SVGRoot.java
Normal file
|
@ -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 <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
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, List<List<SVGElement>> retVec) throws SVGException
|
||||
{
|
||||
if (viewXform != null)
|
||||
{
|
||||
ltw = new AffineTransform(ltw);
|
||||
ltw.concatenate(viewXform);
|
||||
}
|
||||
|
||||
super.doPick(pickArea, ltw, boundingBox, retVec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doPick(Point2D point, boolean boundingBox, List<List<SVGElement>> retVec) throws SVGException
|
||||
{
|
||||
Point2D xPoint = new Point2D.Double(point.getX(), point.getY());
|
||||
if (viewXform != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
viewXform.inverseTransform(point, xPoint);
|
||||
} catch (NoninvertibleTransformException ex)
|
||||
{
|
||||
throw new SVGException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
super.doPick(xPoint, boundingBox, retVec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getShape()
|
||||
{
|
||||
Shape shape = super.getShape();
|
||||
return viewXform.createTransformedShape(shape);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBoundingBox() throws SVGException
|
||||
{
|
||||
Rectangle2D bbox = super.getBoundingBox();
|
||||
return viewXform.createTransformedShape(bbox).getBounds2D();
|
||||
}
|
||||
|
||||
public float getDeviceWidth()
|
||||
{
|
||||
return clipRect.width;
|
||||
}
|
||||
|
||||
public float getDeviceHeight()
|
||||
{
|
||||
return clipRect.height;
|
||||
}
|
||||
|
||||
public Rectangle2D getDeviceRect(Rectangle2D rect)
|
||||
{
|
||||
rect.setRect(clipRect);
|
||||
return rect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event.
|
||||
* Ie, all attributes with track information.
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean shapeChange = false;
|
||||
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
NumberWithUnits newVal = sty.getNumberWithUnits();
|
||||
if (!newVal.equals(x))
|
||||
{
|
||||
x = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
NumberWithUnits newVal = sty.getNumberWithUnits();
|
||||
if (!newVal.equals(y))
|
||||
{
|
||||
y = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("width")))
|
||||
{
|
||||
NumberWithUnits newVal = sty.getNumberWithUnits();
|
||||
if (!newVal.equals(width))
|
||||
{
|
||||
width = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("height")))
|
||||
{
|
||||
NumberWithUnits newVal = sty.getNumberWithUnits();
|
||||
if (!newVal.equals(height))
|
||||
{
|
||||
height = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("viewBox")))
|
||||
{
|
||||
float[] coords = sty.getFloatList();
|
||||
Rectangle2D.Float newViewBox = new Rectangle2D.Float(coords[0], coords[1], coords[2], coords[3]);
|
||||
if (!newViewBox.equals(viewBox))
|
||||
{
|
||||
viewBox = newViewBox;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shapeChange)
|
||||
{
|
||||
build();
|
||||
}
|
||||
|
||||
return changeState || shapeChange;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the styleSheet
|
||||
*/
|
||||
public StyleSheet getStyleSheet()
|
||||
{
|
||||
if (styleSheet == null)
|
||||
{
|
||||
for (int i = 0; i < getNumChildren(); ++i)
|
||||
{
|
||||
SVGElement ele = getChild(i);
|
||||
if (ele instanceof Style)
|
||||
{
|
||||
return ((Style)ele).getStyleSheet();
|
||||
}
|
||||
else if (ele instanceof Defs)
|
||||
{
|
||||
return ((Defs)ele).getStyleSheet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return styleSheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param styleSheet the styleSheet to set
|
||||
*/
|
||||
public void setStyleSheet(StyleSheet styleSheet)
|
||||
{
|
||||
this.styleSheet = styleSheet;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,733 @@
|
|||
/*
|
||||
* 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, 11:43 PM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.app.beans.SVGIcon;
|
||||
import org.xbib.graphics.svg.util.Base64InputStream;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.Serializable;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.XMLReader;
|
||||
|
||||
/**
|
||||
* Many SVG files can be loaded at one time. These files will quite likely need
|
||||
* to reference one another. The SVG universe provides a container for all these
|
||||
* files and the means for them to relate to each other.
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class SVGUniverse implements Serializable
|
||||
{
|
||||
|
||||
public static final long serialVersionUID = 0;
|
||||
transient private PropertyChangeSupport changes = new PropertyChangeSupport(this);
|
||||
/**
|
||||
* Maps document URIs to their loaded SVG diagrams. Note that URIs for
|
||||
* documents loaded from URLs will reflect their URLs and URIs for documents
|
||||
* initiated from streams will have the scheme <i>svgSalamander</i>.
|
||||
*/
|
||||
final HashMap<URI, SVGDiagram> loadedDocs = new HashMap<URI, SVGDiagram>();
|
||||
final HashMap<String, Font> loadedFonts = new HashMap<String, Font>();
|
||||
final HashMap<URL, SoftReference<BufferedImage>> loadedImages = new HashMap<URL, SoftReference<BufferedImage>>();
|
||||
public static final String INPUTSTREAM_SCHEME = "svgSalamander";
|
||||
/**
|
||||
* Current time in this universe. Used for resolving attributes that are
|
||||
* influenced by track information. Time is in milliseconds. Time 0
|
||||
* corresponds to the time of 0 in each member diagram.
|
||||
*/
|
||||
protected double curTime = 0.0;
|
||||
private boolean verbose = false;
|
||||
|
||||
//If true, <imageSVG> elements will only load image data that is included using inline data: uris
|
||||
private boolean imageDataInlineOnly = false;
|
||||
|
||||
/**
|
||||
* Creates a new instance of SVGUniverse
|
||||
*/
|
||||
public SVGUniverse()
|
||||
{
|
||||
}
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener l)
|
||||
{
|
||||
changes.addPropertyChangeListener(l);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener l)
|
||||
{
|
||||
changes.removePropertyChangeListener(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release all loaded SVG document from memory
|
||||
*/
|
||||
public void clear()
|
||||
{
|
||||
loadedDocs.clear();
|
||||
loadedFonts.clear();
|
||||
loadedImages.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current animation time in milliseconds.
|
||||
*/
|
||||
public double getCurTime()
|
||||
{
|
||||
return curTime;
|
||||
}
|
||||
|
||||
public void setCurTime(double curTime)
|
||||
{
|
||||
double oldTime = this.curTime;
|
||||
this.curTime = curTime;
|
||||
changes.firePropertyChange("curTime", new Double(oldTime), new Double(curTime));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all time influenced style and presentation attributes in all SVG
|
||||
* documents in this universe.
|
||||
*/
|
||||
public void updateTime() throws SVGException
|
||||
{
|
||||
for (SVGDiagram dia : loadedDocs.values()) {
|
||||
dia.updateTime(curTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the Font element to let the universe know that a font has been
|
||||
* loaded and is available.
|
||||
*/
|
||||
void registerFont(Font font)
|
||||
{
|
||||
loadedFonts.put(font.getFontFace().getFontFamily(), font);
|
||||
}
|
||||
|
||||
public Font getDefaultFont()
|
||||
{
|
||||
for (Font font : loadedFonts.values()) {
|
||||
return font;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Font getFont(String fontName)
|
||||
{
|
||||
return (Font) loadedFonts.get(fontName);
|
||||
}
|
||||
|
||||
URL registerImage(URI imageURI)
|
||||
{
|
||||
String scheme = imageURI.getScheme();
|
||||
if (scheme.equals("data"))
|
||||
{
|
||||
String path = imageURI.getRawSchemeSpecificPart();
|
||||
int idx = path.indexOf(';');
|
||||
String mime = path.substring(0, idx);
|
||||
String content = path.substring(idx + 1);
|
||||
|
||||
if (content.startsWith("base64"))
|
||||
{
|
||||
content = content.substring(6);
|
||||
try
|
||||
{
|
||||
// byte[] buf = new sun.misc.BASE64Decoder().decodeBuffer(content);
|
||||
// ByteArrayInputStream bais = new ByteArrayInputStream(buf);
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(content.getBytes());
|
||||
Base64InputStream bais = new Base64InputStream(bis);
|
||||
|
||||
BufferedImage img = ImageIO.read(bais);
|
||||
|
||||
URL url;
|
||||
int urlIdx = 0;
|
||||
while (true)
|
||||
{
|
||||
url = new URL("inlineImage", "localhost", "img" + urlIdx);
|
||||
if (!loadedImages.containsKey(url))
|
||||
{
|
||||
break;
|
||||
}
|
||||
urlIdx++;
|
||||
}
|
||||
|
||||
SoftReference<BufferedImage> ref = new SoftReference<BufferedImage>(img);
|
||||
loadedImages.put(url, ref);
|
||||
|
||||
return url;
|
||||
} catch (IOException ex)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not decode inline image", ex);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} else
|
||||
{
|
||||
try
|
||||
{
|
||||
URL url = imageURI.toURL();
|
||||
registerImage(url);
|
||||
return url;
|
||||
} catch (MalformedURLException ex)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Bad url", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void registerImage(URL imageURL)
|
||||
{
|
||||
if (loadedImages.containsKey(imageURL))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SoftReference<BufferedImage> ref;
|
||||
try
|
||||
{
|
||||
String fileName = imageURL.getFile();
|
||||
if (".svg".equals(fileName.substring(fileName.length() - 4).toLowerCase()))
|
||||
{
|
||||
SVGIcon icon = new SVGIcon();
|
||||
icon.setSvgURI(imageURL.toURI());
|
||||
|
||||
BufferedImage img = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g = img.createGraphics();
|
||||
icon.paintIcon(null, g, 0, 0);
|
||||
g.dispose();
|
||||
ref = new SoftReference<BufferedImage>(img);
|
||||
} else
|
||||
{
|
||||
BufferedImage img = ImageIO.read(imageURL);
|
||||
ref = new SoftReference<BufferedImage>(img);
|
||||
}
|
||||
loadedImages.put(imageURL, ref);
|
||||
} catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not load image: " + imageURL, e);
|
||||
}
|
||||
}
|
||||
|
||||
BufferedImage getImage(URL imageURL)
|
||||
{
|
||||
SoftReference<BufferedImage> ref = (SoftReference<BufferedImage>) loadedImages.get(imageURL);
|
||||
if (ref == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
BufferedImage img = (BufferedImage) ref.get();
|
||||
//If image was cleared from memory, reload it
|
||||
if (img == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
img = ImageIO.read(imageURL);
|
||||
} catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not load image", e);
|
||||
}
|
||||
ref = new SoftReference<BufferedImage>(img);
|
||||
loadedImages.put(imageURL, ref);
|
||||
}
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the element of the document at the given URI. If the document is
|
||||
* not already loaded, it will be.
|
||||
*/
|
||||
public SVGElement getElement(URI path)
|
||||
{
|
||||
return getElement(path, true);
|
||||
}
|
||||
|
||||
public SVGElement getElement(URL path)
|
||||
{
|
||||
try
|
||||
{
|
||||
URI uri = new URI(path.toString());
|
||||
return getElement(uri, true);
|
||||
} catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not parse url " + path, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public URI cleanUri(URI uri)
|
||||
{
|
||||
String scheme = uri.getScheme();
|
||||
String schemeSpecific = uri.getSchemeSpecificPart();
|
||||
String frag = uri.getFragment();
|
||||
|
||||
if (schemeSpecific.startsWith("file:///"))
|
||||
{
|
||||
//Work around for URIs of resources obtained by Class.getResource()
|
||||
schemeSpecific = "file:/" + schemeSpecific.substring(8);
|
||||
}
|
||||
else
|
||||
{
|
||||
return uri;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return new URI(scheme, schemeSpecific, frag);
|
||||
}
|
||||
catch (URISyntaxException ex)
|
||||
{
|
||||
Logger.getLogger(SVGUniverse.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a href within our universe. If the href refers to a document
|
||||
* that is not loaded, it will be loaded. The URL #target will then be
|
||||
* checked against the SVG diagram's index and the corresponding element
|
||||
* returned. If there is no corresponding index, null is returned.
|
||||
*/
|
||||
public SVGElement getElement(URI path, boolean loadIfAbsent)
|
||||
{
|
||||
try
|
||||
{
|
||||
path = cleanUri(path);
|
||||
|
||||
//Strip fragment from URI
|
||||
URI xmlBase = new URI(path.getScheme(), path.getSchemeSpecificPart(), null);
|
||||
|
||||
SVGDiagram dia = (SVGDiagram) loadedDocs.get(xmlBase);
|
||||
if (dia == null && loadIfAbsent)
|
||||
{
|
||||
//System.err.println("SVGUnivserse: " + xmlBase.toString());
|
||||
//javax.swing.JOptionPane.showMessageDialog(null, xmlBase.toString());
|
||||
URL url = xmlBase.toURL();
|
||||
|
||||
loadSVG(url, false);
|
||||
dia = (SVGDiagram) loadedDocs.get(xmlBase);
|
||||
if (dia == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String fragment = path.getFragment();
|
||||
return fragment == null ? dia.getRoot() : dia.getElement(fragment);
|
||||
} catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not parse path " + path, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public SVGDiagram getDiagram(URI xmlBase)
|
||||
{
|
||||
return getDiagram(xmlBase, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the diagram that has been loaded from this root. If diagram is
|
||||
* not already loaded, returns null.
|
||||
*/
|
||||
public SVGDiagram getDiagram(URI xmlBase, boolean loadIfAbsent)
|
||||
{
|
||||
if (xmlBase == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
SVGDiagram dia = (SVGDiagram) loadedDocs.get(xmlBase);
|
||||
if (dia != null || !loadIfAbsent)
|
||||
{
|
||||
return dia;
|
||||
}
|
||||
|
||||
//Load missing diagram
|
||||
try
|
||||
{
|
||||
URL url;
|
||||
if ("jar".equals(xmlBase.getScheme()) && xmlBase.getPath() != null && !xmlBase.getPath().contains("!/"))
|
||||
{
|
||||
//Workaround for resources stored in jars loaded by Webstart.
|
||||
//http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6753651
|
||||
url = SVGUniverse.class.getResource(xmlBase.getPath());
|
||||
}
|
||||
else
|
||||
{
|
||||
url = xmlBase.toURL();
|
||||
}
|
||||
|
||||
|
||||
loadSVG(url, false);
|
||||
dia = (SVGDiagram) loadedDocs.get(xmlBase);
|
||||
return dia;
|
||||
} catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not parse", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps input stream in a BufferedInputStream. If it is detected that this
|
||||
* input stream is GZIPped, also wraps in a GZIPInputStream for inflation.
|
||||
*
|
||||
* @param is Raw input stream
|
||||
* @return Uncompressed stream of SVG data
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
private InputStream createDocumentInputStream(InputStream is) throws IOException
|
||||
{
|
||||
BufferedInputStream bin = new BufferedInputStream(is);
|
||||
bin.mark(2);
|
||||
int b0 = bin.read();
|
||||
int b1 = bin.read();
|
||||
bin.reset();
|
||||
|
||||
//Check for gzip magic number
|
||||
if ((b1 << 8 | b0) == GZIPInputStream.GZIP_MAGIC)
|
||||
{
|
||||
GZIPInputStream iis = new GZIPInputStream(bin);
|
||||
return iis;
|
||||
} else
|
||||
{
|
||||
//Plain text
|
||||
return bin;
|
||||
}
|
||||
}
|
||||
|
||||
public URI loadSVG(URL docRoot)
|
||||
{
|
||||
return loadSVG(docRoot, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an SVG file and all the files it references from the URL provided.
|
||||
* If a referenced file already exists in the SVG universe, it is not
|
||||
* reloaded.
|
||||
*
|
||||
* @param docRoot - URL to the location where this SVG file can be found.
|
||||
* @param forceLoad - if true, ignore cached diagram and reload
|
||||
* @return - The URI that refers to the loaded document
|
||||
*/
|
||||
public URI loadSVG(URL docRoot, boolean forceLoad)
|
||||
{
|
||||
try
|
||||
{
|
||||
URI uri = new URI(docRoot.toString());
|
||||
if (loadedDocs.containsKey(uri) && !forceLoad)
|
||||
{
|
||||
return uri;
|
||||
}
|
||||
|
||||
InputStream is = docRoot.openStream();
|
||||
URI result = loadSVG(uri, new InputSource(createDocumentInputStream(is)));
|
||||
is.close();
|
||||
return result;
|
||||
} catch (URISyntaxException ex)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not parse", ex);
|
||||
} catch (IOException e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not parse", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public URI loadSVG(InputStream is, String name) throws IOException
|
||||
{
|
||||
return loadSVG(is, name, false);
|
||||
}
|
||||
|
||||
public URI loadSVG(InputStream is, String name, boolean forceLoad) throws IOException
|
||||
{
|
||||
URI uri = getStreamBuiltURI(name);
|
||||
if (uri == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (loadedDocs.containsKey(uri) && !forceLoad)
|
||||
{
|
||||
return uri;
|
||||
}
|
||||
|
||||
return loadSVG(uri, new InputSource(createDocumentInputStream(is)));
|
||||
}
|
||||
|
||||
public URI loadSVG(Reader reader, String name)
|
||||
{
|
||||
return loadSVG(reader, name, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine allows you to create SVG documents from data streams that
|
||||
* may not necessarily have a URL to load from. Since every SVG document
|
||||
* must be identified by a unique URL, Salamander provides a method to fake
|
||||
* this for streams by defining it's own protocol - svgSalamander - for SVG
|
||||
* documents without a formal URL.
|
||||
*
|
||||
* @param reader - A stream containing a valid SVG document
|
||||
* @param name - <p>A 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.</p> <p>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.</p> <p>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</p> <p>If a name does not start with the character '/',
|
||||
* it will be automatically prefixed to it.</p>
|
||||
* @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 ThreadLocal<SAXParser> threadSAXParser = new ThreadLocal<SAXParser>();
|
||||
|
||||
private XMLReader getXMLReader() throws SAXException, ParserConfigurationException
|
||||
{
|
||||
SAXParser saxParser = threadSAXParser.get();
|
||||
if (saxParser == null)
|
||||
{
|
||||
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
|
||||
saxParserFactory.setNamespaceAware(true);
|
||||
saxParser = saxParserFactory.newSAXParser();
|
||||
threadSAXParser.set(saxParser);
|
||||
}
|
||||
return saxParser.getXMLReader();
|
||||
}
|
||||
|
||||
protected URI loadSVG(URI xmlBase, InputSource is)
|
||||
{
|
||||
xmlBase = cleanUri(xmlBase);
|
||||
|
||||
|
||||
// Use an instance of ourselves as the SAX event handler
|
||||
SVGLoader handler = new SVGLoader(xmlBase, this, verbose);
|
||||
|
||||
//Place this docment in the universe before it is completely loaded
|
||||
// so that the load process can refer to references within it's current
|
||||
// document
|
||||
loadedDocs.put(xmlBase, handler.getLoadedDiagram());
|
||||
|
||||
try
|
||||
{
|
||||
// Parse the input
|
||||
XMLReader reader = getXMLReader();
|
||||
reader.setEntityResolver(
|
||||
new EntityResolver()
|
||||
{
|
||||
public InputSource resolveEntity(String publicId, String systemId)
|
||||
{
|
||||
//Ignore all DTDs
|
||||
return new InputSource(new ByteArrayInputStream(new byte[0]));
|
||||
}
|
||||
});
|
||||
reader.setContentHandler(handler);
|
||||
reader.parse(is);
|
||||
|
||||
handler.getLoadedDiagram().updateTime(curTime);
|
||||
return xmlBase;
|
||||
} catch (SAXParseException sex)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Error processing " + xmlBase, sex);
|
||||
|
||||
loadedDocs.remove(xmlBase);
|
||||
return null;
|
||||
} catch (Throwable e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not load SVG " + xmlBase, e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of uris of all loaded documents and subdocuments.
|
||||
* @return
|
||||
*/
|
||||
public ArrayList<URI> getLoadedDocumentURIs()
|
||||
{
|
||||
return new ArrayList<URI>(loadedDocs.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove loaded document from cache.
|
||||
* @param uri
|
||||
*/
|
||||
public void removeDocument(URI uri)
|
||||
{
|
||||
uri = cleanUri(uri);
|
||||
loadedDocs.remove(uri);
|
||||
}
|
||||
|
||||
public boolean isVerbose()
|
||||
{
|
||||
return verbose;
|
||||
}
|
||||
|
||||
public void setVerbose(boolean verbose)
|
||||
{
|
||||
this.verbose = verbose;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses serialization to duplicate this universe.
|
||||
*/
|
||||
public SVGUniverse duplicate() throws IOException, ClassNotFoundException
|
||||
{
|
||||
ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
||||
ObjectOutputStream os = new ObjectOutputStream(bs);
|
||||
os.writeObject(this);
|
||||
os.close();
|
||||
|
||||
ByteArrayInputStream bin = new ByteArrayInputStream(bs.toByteArray());
|
||||
ObjectInputStream is = new ObjectInputStream(bin);
|
||||
SVGUniverse universe = (SVGUniverse) is.readObject();
|
||||
is.close();
|
||||
|
||||
return universe;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the imageDataInlineOnly
|
||||
*/
|
||||
public boolean isImageDataInlineOnly()
|
||||
{
|
||||
return imageDataInlineOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param imageDataInlineOnly the imageDataInlineOnly to set
|
||||
*/
|
||||
public void setImageDataInlineOnly(boolean imageDataInlineOnly)
|
||||
{
|
||||
this.imageDataInlineOnly = imageDataInlineOnly;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,448 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 5:21 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.Marker.MarkerLayout;
|
||||
import org.xbib.graphics.svg.Marker.MarkerPos;
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Paint;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Parent of shape objects
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
abstract public class ShapeElement extends RenderableElement
|
||||
{
|
||||
|
||||
/**
|
||||
* This is necessary to get text elements to render the stroke the correct
|
||||
* width. It is an alternative to producing new font glyph sets at different
|
||||
* sizes.
|
||||
*/
|
||||
protected float strokeWidthScalar = 1f;
|
||||
|
||||
/** Creates a new instance of ShapeElement */
|
||||
public ShapeElement() {
|
||||
}
|
||||
|
||||
@Override
|
||||
abstract protected void doRender(java.awt.Graphics2D g) throws SVGException;
|
||||
|
||||
/*
|
||||
protected void setStrokeWidthScalar(float strokeWidthScalar)
|
||||
{
|
||||
this.strokeWidthScalar = strokeWidthScalar;
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected void doPick(Point2D point, boolean boundingBox, List<List<SVGElement>> retVec) throws SVGException
|
||||
{
|
||||
// StyleAttribute styleAttrib = new StyleAttribute();
|
||||
// if (getStyle(styleAttrib.setName("fill")) && getShape().contains(point))
|
||||
if ((boundingBox ? getBoundingBox() : getShape()).contains(point))
|
||||
{
|
||||
retVec.add(getPath(null));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPick(Rectangle2D pickArea, AffineTransform ltw, boolean boundingBox, List<List<SVGElement>> retVec) throws SVGException
|
||||
{
|
||||
// StyleAttribute styleAttrib = new StyleAttribute();
|
||||
// if (getStyle(styleAttrib.setName("fill")) && getShape().contains(point))
|
||||
if (ltw.createTransformedShape((boundingBox ? getBoundingBox() : getShape())).intersects(pickArea))
|
||||
{
|
||||
retVec.add(getPath(null));
|
||||
}
|
||||
}
|
||||
|
||||
private Paint handleCurrentColor(StyleAttribute styleAttrib) throws SVGException
|
||||
{
|
||||
if (styleAttrib.getStringValue().equals("currentColor"))
|
||||
{
|
||||
StyleAttribute currentColorAttrib = new StyleAttribute();
|
||||
if (getStyle(currentColorAttrib.setName("color")))
|
||||
{
|
||||
if (!currentColorAttrib.getStringValue().equals("none"))
|
||||
{
|
||||
return currentColorAttrib.getColorValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return styleAttrib.getColorValue();
|
||||
}
|
||||
}
|
||||
|
||||
protected void renderShape(Graphics2D g, Shape shape) throws SVGException
|
||||
{
|
||||
//g.setColor(Color.green);
|
||||
|
||||
StyleAttribute styleAttrib = new StyleAttribute();
|
||||
|
||||
//Don't process if not visible
|
||||
if (getStyle(styleAttrib.setName("visibility")))
|
||||
{
|
||||
if (!styleAttrib.getStringValue().equals("visible")) return;
|
||||
}
|
||||
|
||||
if (getStyle(styleAttrib.setName("display")))
|
||||
{
|
||||
if (styleAttrib.getStringValue().equals("none")) return;
|
||||
}
|
||||
|
||||
//None, solid color, gradient, pattern
|
||||
Paint fillPaint = Color.black; //Default to black. Must be explicitly set to none for no fill.
|
||||
if (getStyle(styleAttrib.setName("fill")))
|
||||
{
|
||||
if (styleAttrib.getStringValue().equals("none")) fillPaint = null;
|
||||
else
|
||||
{
|
||||
fillPaint = handleCurrentColor(styleAttrib);
|
||||
if (fillPaint == null)
|
||||
{
|
||||
URI uri = styleAttrib.getURIValue(getXMLBase());
|
||||
if (uri != null)
|
||||
{
|
||||
Rectangle2D bounds = shape.getBounds2D();
|
||||
AffineTransform xform = g.getTransform();
|
||||
|
||||
SVGElement ele = diagram.getUniverse().getElement(uri);
|
||||
if (ele != null)
|
||||
{
|
||||
try {
|
||||
fillPaint = ((FillElement)ele).getPaint(bounds, xform);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new SVGException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Default opacity
|
||||
float opacity = 1f;
|
||||
if (getStyle(styleAttrib.setName("opacity")))
|
||||
{
|
||||
opacity = styleAttrib.getRatioValue();
|
||||
}
|
||||
|
||||
float fillOpacity = opacity;
|
||||
if (getStyle(styleAttrib.setName("fill-opacity")))
|
||||
{
|
||||
fillOpacity *= styleAttrib.getRatioValue();
|
||||
}
|
||||
|
||||
|
||||
Paint strokePaint = null; //Default is to stroke with none
|
||||
if (getStyle(styleAttrib.setName("stroke")))
|
||||
{
|
||||
if (styleAttrib.getStringValue().equals("none")) strokePaint = null;
|
||||
else
|
||||
{
|
||||
strokePaint = handleCurrentColor(styleAttrib);
|
||||
if (strokePaint == null)
|
||||
{
|
||||
URI uri = styleAttrib.getURIValue(getXMLBase());
|
||||
if (uri != null)
|
||||
{
|
||||
Rectangle2D bounds = shape.getBounds2D();
|
||||
AffineTransform xform = g.getTransform();
|
||||
|
||||
SVGElement ele = diagram.getUniverse().getElement(uri);
|
||||
if (ele != null)
|
||||
{
|
||||
strokePaint = ((FillElement)ele).getPaint(bounds, xform);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float[] strokeDashArray = null;
|
||||
if (getStyle(styleAttrib.setName("stroke-dasharray")))
|
||||
{
|
||||
strokeDashArray = styleAttrib.getFloatList();
|
||||
if (strokeDashArray.length == 0) strokeDashArray = null;
|
||||
}
|
||||
|
||||
float strokeDashOffset = 0f;
|
||||
if (getStyle(styleAttrib.setName("stroke-dashoffset")))
|
||||
{
|
||||
strokeDashOffset = styleAttrib.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
int strokeLinecap = BasicStroke.CAP_BUTT;
|
||||
if (getStyle(styleAttrib.setName("stroke-linecap")))
|
||||
{
|
||||
String val = styleAttrib.getStringValue();
|
||||
if (val.equals("round"))
|
||||
{
|
||||
strokeLinecap = BasicStroke.CAP_ROUND;
|
||||
}
|
||||
else if (val.equals("square"))
|
||||
{
|
||||
strokeLinecap = BasicStroke.CAP_SQUARE;
|
||||
}
|
||||
}
|
||||
|
||||
int strokeLinejoin = BasicStroke.JOIN_MITER;
|
||||
if (getStyle(styleAttrib.setName("stroke-linejoin")))
|
||||
{
|
||||
String val = styleAttrib.getStringValue();
|
||||
if (val.equals("round"))
|
||||
{
|
||||
strokeLinejoin = BasicStroke.JOIN_ROUND;
|
||||
}
|
||||
else if (val.equals("bevel"))
|
||||
{
|
||||
strokeLinejoin = BasicStroke.JOIN_BEVEL;
|
||||
}
|
||||
}
|
||||
|
||||
float strokeMiterLimit = 4f;
|
||||
if (getStyle(styleAttrib.setName("stroke-miterlimit")))
|
||||
{
|
||||
strokeMiterLimit = Math.max(styleAttrib.getFloatValueWithUnits(), 1);
|
||||
}
|
||||
|
||||
float strokeOpacity = opacity;
|
||||
if (getStyle(styleAttrib.setName("stroke-opacity")))
|
||||
{
|
||||
strokeOpacity *= styleAttrib.getRatioValue();
|
||||
}
|
||||
|
||||
float strokeWidth = 1f;
|
||||
if (getStyle(styleAttrib.setName("stroke-width")))
|
||||
{
|
||||
strokeWidth = styleAttrib.getFloatValueWithUnits();
|
||||
}
|
||||
// if (strokeWidthScalar != 1f)
|
||||
// {
|
||||
strokeWidth *= strokeWidthScalar;
|
||||
// }
|
||||
|
||||
Marker markerStart = null;
|
||||
if (getStyle(styleAttrib.setName("marker-start")))
|
||||
{
|
||||
if (!styleAttrib.getStringValue().equals("none"))
|
||||
{
|
||||
URI uri = styleAttrib.getURIValue(getXMLBase());
|
||||
markerStart = (Marker)diagram.getUniverse().getElement(uri);
|
||||
}
|
||||
}
|
||||
|
||||
Marker markerMid = null;
|
||||
if (getStyle(styleAttrib.setName("marker-mid")))
|
||||
{
|
||||
if (!styleAttrib.getStringValue().equals("none"))
|
||||
{
|
||||
URI uri = styleAttrib.getURIValue(getXMLBase());
|
||||
markerMid = (Marker)diagram.getUniverse().getElement(uri);
|
||||
}
|
||||
}
|
||||
|
||||
Marker markerEnd = null;
|
||||
if (getStyle(styleAttrib.setName("marker-end")))
|
||||
{
|
||||
if (!styleAttrib.getStringValue().equals("none"))
|
||||
{
|
||||
URI uri = styleAttrib.getURIValue(getXMLBase());
|
||||
markerEnd = (Marker)diagram.getUniverse().getElement(uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Draw the shape
|
||||
if (fillPaint != null && fillOpacity != 0f)
|
||||
{
|
||||
if (fillOpacity <= 0)
|
||||
{
|
||||
//Do nothing
|
||||
}
|
||||
else if (fillOpacity < 1f)
|
||||
{
|
||||
Composite cachedComposite = g.getComposite();
|
||||
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, fillOpacity));
|
||||
|
||||
g.setPaint(fillPaint);
|
||||
g.fill(shape);
|
||||
|
||||
g.setComposite(cachedComposite);
|
||||
}
|
||||
else
|
||||
{
|
||||
g.setPaint(fillPaint);
|
||||
g.fill(shape);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (strokePaint != null && strokeOpacity != 0f)
|
||||
{
|
||||
BasicStroke stroke;
|
||||
if (strokeDashArray == null)
|
||||
{
|
||||
stroke = new BasicStroke(strokeWidth, strokeLinecap, strokeLinejoin, strokeMiterLimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
stroke = new BasicStroke(strokeWidth, strokeLinecap, strokeLinejoin, strokeMiterLimit, strokeDashArray, strokeDashOffset);
|
||||
}
|
||||
|
||||
Shape strokeShape;
|
||||
AffineTransform cacheXform = g.getTransform();
|
||||
if (vectorEffect == VECTOR_EFFECT_NON_SCALING_STROKE)
|
||||
{
|
||||
strokeShape = cacheXform.createTransformedShape(shape);
|
||||
strokeShape = stroke.createStrokedShape(strokeShape);
|
||||
}
|
||||
else
|
||||
{
|
||||
strokeShape = stroke.createStrokedShape(shape);
|
||||
}
|
||||
|
||||
if (strokeOpacity <= 0)
|
||||
{
|
||||
//Do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
Composite cachedComposite = g.getComposite();
|
||||
|
||||
if (strokeOpacity < 1f)
|
||||
{
|
||||
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, strokeOpacity));
|
||||
}
|
||||
|
||||
if (vectorEffect == VECTOR_EFFECT_NON_SCALING_STROKE)
|
||||
{
|
||||
//Set to identity
|
||||
g.setTransform(new AffineTransform());
|
||||
}
|
||||
|
||||
g.setPaint(strokePaint);
|
||||
g.fill(strokeShape);
|
||||
|
||||
if (vectorEffect == VECTOR_EFFECT_NON_SCALING_STROKE)
|
||||
{
|
||||
//Set to identity
|
||||
g.setTransform(cacheXform);
|
||||
}
|
||||
|
||||
if (strokeOpacity < 1f)
|
||||
{
|
||||
g.setComposite(cachedComposite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (markerStart != null || markerMid != null || markerEnd != null)
|
||||
{
|
||||
MarkerLayout layout = new MarkerLayout();
|
||||
layout.layout(shape);
|
||||
|
||||
ArrayList<MarkerPos> list = layout.getMarkerList();
|
||||
for (int i = 0; i < list.size(); ++i)
|
||||
{
|
||||
MarkerPos pos = list.get(i);
|
||||
|
||||
switch (pos.type)
|
||||
{
|
||||
case Marker.MARKER_START:
|
||||
if (markerStart != null)
|
||||
{
|
||||
markerStart.render(g, pos, strokeWidth);
|
||||
}
|
||||
break;
|
||||
case Marker.MARKER_MID:
|
||||
if (markerMid != null)
|
||||
{
|
||||
markerMid.render(g, pos, strokeWidth);
|
||||
}
|
||||
break;
|
||||
case Marker.MARKER_END:
|
||||
if (markerEnd != null)
|
||||
{
|
||||
markerEnd.render(g, pos, strokeWidth);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract public Shape getShape();
|
||||
|
||||
protected Rectangle2D includeStrokeInBounds(Rectangle2D rect) throws SVGException
|
||||
{
|
||||
StyleAttribute styleAttrib = new StyleAttribute();
|
||||
if (!getStyle(styleAttrib.setName("stroke"))) return rect;
|
||||
|
||||
double strokeWidth = 1;
|
||||
if (getStyle(styleAttrib.setName("stroke-width"))) strokeWidth = styleAttrib.getDoubleValue();
|
||||
|
||||
rect.setRect(
|
||||
rect.getX() - strokeWidth / 2,
|
||||
rect.getY() - strokeWidth / 2,
|
||||
rect.getWidth() + strokeWidth,
|
||||
rect.getHeight() + strokeWidth);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
}
|
150
graphics-svg/src/main/java/org/xbib/graphics/svg/Stop.java
Normal file
150
graphics-svg/src/main/java/org/xbib/graphics/svg/Stop.java
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 1:56 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Color;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Stop extends SVGElement
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "stop";
|
||||
float offset = 0f;
|
||||
float opacity = 1f;
|
||||
Color color = Color.black;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Stop
|
||||
*/
|
||||
public Stop()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("offset")))
|
||||
{
|
||||
offset = sty.getFloatValue();
|
||||
String units = sty.getUnits();
|
||||
if (units != null && units.equals("%"))
|
||||
{
|
||||
offset /= 100f;
|
||||
}
|
||||
if (offset > 1)
|
||||
{
|
||||
offset = 1;
|
||||
}
|
||||
if (offset < 0)
|
||||
{
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (getStyle(sty.setName("stop-color")))
|
||||
{
|
||||
color = sty.getColorValue();
|
||||
}
|
||||
|
||||
if (getStyle(sty.setName("stop-opacity")))
|
||||
{
|
||||
opacity = sty.getRatioValue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean shapeChange = false;
|
||||
|
||||
if (getPres(sty.setName("offset")))
|
||||
{
|
||||
float newVal = sty.getFloatValue();
|
||||
if (newVal != offset)
|
||||
{
|
||||
offset = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getStyle(sty.setName("stop-color")))
|
||||
{
|
||||
Color newVal = sty.getColorValue();
|
||||
if (newVal != color)
|
||||
{
|
||||
color = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getStyle(sty.setName("stop-opacity")))
|
||||
{
|
||||
float newVal = sty.getFloatValue();
|
||||
if (newVal != opacity)
|
||||
{
|
||||
opacity = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
return shapeChange;
|
||||
}
|
||||
}
|
110
graphics-svg/src/main/java/org/xbib/graphics/svg/Style.java
Normal file
110
graphics-svg/src/main/java/org/xbib/graphics/svg/Style.java
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* 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 September 19, 2004, 1:56 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import org.xbib.graphics.svg.xml.StyleSheet;
|
||||
|
||||
/**
|
||||
* Holds title textual information within tree
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Style extends SVGElement
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "style";
|
||||
//Should be set to "text/css"
|
||||
String type;
|
||||
StringBuffer text = new StringBuffer();
|
||||
|
||||
StyleSheet styleSheet;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Stop
|
||||
*/
|
||||
public Style()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during load process to add text scanned within a tag
|
||||
*/
|
||||
@Override
|
||||
public void loaderAddText(SVGLoaderHelper helper, String text)
|
||||
{
|
||||
this.text.append(text);
|
||||
|
||||
//Invalidate style sheet
|
||||
styleSheet = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("type")))
|
||||
{
|
||||
type = sty.getStringValue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
//Style sheet doesn't change
|
||||
return false;
|
||||
}
|
||||
|
||||
public StyleSheet getStyleSheet()
|
||||
{
|
||||
if (styleSheet == null && text.length() > 0)
|
||||
{
|
||||
styleSheet = StyleSheet.parseSheet(text.toString());
|
||||
}
|
||||
return styleSheet;
|
||||
}
|
||||
}
|
155
graphics-svg/src/main/java/org/xbib/graphics/svg/Symbol.java
Normal file
155
graphics-svg/src/main/java/org/xbib/graphics/svg/Symbol.java
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 1:56 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Symbol extends Group
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "symbol";
|
||||
AffineTransform viewXform;
|
||||
Rectangle2D viewBox;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Stop
|
||||
*/
|
||||
public Symbol()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
// sty = getPres("unicode");
|
||||
// if (sty != null) unicode = sty.getStringValue();
|
||||
|
||||
|
||||
if (getPres(sty.setName("viewBox")))
|
||||
{
|
||||
float[] dim = sty.getFloatList();
|
||||
viewBox = new Rectangle2D.Float(dim[0], dim[1], dim[2], dim[3]);
|
||||
}
|
||||
|
||||
if (viewBox == null)
|
||||
{
|
||||
// viewBox = super.getBoundingBox();
|
||||
viewBox = new Rectangle(0, 0, 1, 1);
|
||||
}
|
||||
|
||||
//Transform pattern onto unit square
|
||||
viewXform = new AffineTransform();
|
||||
viewXform.scale(1.0 / viewBox.getWidth(), 1.0 / viewBox.getHeight());
|
||||
viewXform.translate(-viewBox.getX(), -viewBox.getY());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean outsideClip(Graphics2D g) throws SVGException
|
||||
{
|
||||
Shape clip = g.getClip();
|
||||
// g.getClipBounds(clipBounds);
|
||||
Rectangle2D rect = super.getBoundingBox();
|
||||
if (clip == null || clip.intersects(rect))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRender(Graphics2D g) throws SVGException
|
||||
{
|
||||
AffineTransform oldXform = g.getTransform();
|
||||
g.transform(viewXform);
|
||||
|
||||
super.doRender(g);
|
||||
|
||||
g.setTransform(oldXform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getShape()
|
||||
{
|
||||
Shape shape = super.getShape();
|
||||
return viewXform.createTransformedShape(shape);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBoundingBox() throws SVGException
|
||||
{
|
||||
Rectangle2D rect = super.getBoundingBox();
|
||||
return viewXform.createTransformedShape(rect).getBounds2D();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
|
||||
//View box properties do not change
|
||||
|
||||
return changeState;
|
||||
}
|
||||
}
|
215
graphics-svg/src/main/java/org/xbib/graphics/svg/Text.java
Normal file
215
graphics-svg/src/main/java/org/xbib/graphics/svg/Text.java
Normal file
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 1:56 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.util.FontUtil;
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Text extends Tspan
|
||||
{
|
||||
public static final String TAG_NAME = "text";
|
||||
|
||||
public static final int TXAN_START = 0;
|
||||
public static final int TXAN_MIDDLE = 1;
|
||||
public static final int TXAN_END = 2;
|
||||
public static final int TXST_NORMAL = 0;
|
||||
public static final int TXST_ITALIC = 1;
|
||||
public static final int TXST_OBLIQUE = 2;
|
||||
public static final int TXWE_NORMAL = 0;
|
||||
public static final int TXWE_BOLD = 1;
|
||||
public static final int TXWE_BOLDER = 2;
|
||||
public static final int TXWE_LIGHTER = 3;
|
||||
public static final int TXWE_100 = 4;
|
||||
public static final int TXWE_200 = 5;
|
||||
public static final int TXWE_300 = 6;
|
||||
public static final int TXWE_400 = 7;
|
||||
public static final int TXWE_500 = 8;
|
||||
public static final int TXWE_600 = 9;
|
||||
public static final int TXWE_700 = 10;
|
||||
public static final int TXWE_800 = 11;
|
||||
public static final int TXWE_900 = 12;
|
||||
|
||||
int textAnchor = TXAN_START;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Stop
|
||||
*/
|
||||
public Text()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard cached information
|
||||
*/
|
||||
public void rebuild() throws SVGException
|
||||
{
|
||||
build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
buildText();
|
||||
}
|
||||
|
||||
protected void buildAttributes(StyleAttribute sty) throws SVGException
|
||||
{
|
||||
super.buildAttributes(sty);
|
||||
if (getStyle(sty.setName("text-anchor")))
|
||||
{
|
||||
String s = sty.getStringValue();
|
||||
if (s.equals("middle"))
|
||||
{
|
||||
textAnchor = TXAN_MIDDLE;
|
||||
} else if (s.equals("end"))
|
||||
{
|
||||
textAnchor = TXAN_END;
|
||||
} else
|
||||
{
|
||||
textAnchor = TXAN_START;
|
||||
}
|
||||
} else
|
||||
{
|
||||
textAnchor = TXAN_START;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void buildText() throws SVGException
|
||||
{
|
||||
Cursor cursor = createInitialCursor();
|
||||
float xInitial = cursor.x;
|
||||
super.buildTextShape(cursor);
|
||||
alignSegmentsAtAnchor(fullPath, xInitial);
|
||||
}
|
||||
|
||||
private void alignSegmentsAtAnchor(Path2D textPath, float xInitial)
|
||||
{
|
||||
AffineTransform tx;
|
||||
Rectangle2D bounds;
|
||||
switch (textAnchor)
|
||||
{
|
||||
case TXAN_MIDDLE:
|
||||
bounds = textPath.getBounds2D();
|
||||
tx = AffineTransform.getTranslateInstance(
|
||||
-(bounds.getX() + bounds.getWidth() / 2.0 - xInitial), 0
|
||||
);
|
||||
break;
|
||||
case TXAN_END:
|
||||
bounds = textPath.getBounds2D();
|
||||
tx = AffineTransform.getTranslateInstance(
|
||||
-(bounds.getX() + bounds.getWidth() - xInitial), 0
|
||||
);
|
||||
break;
|
||||
default:
|
||||
tx = null;
|
||||
break;
|
||||
}
|
||||
if (tx != null)
|
||||
{
|
||||
fullPath.transform(tx);
|
||||
textBounds = fullPath.getBounds2D();
|
||||
transformSegments(segments, tx);
|
||||
}
|
||||
}
|
||||
|
||||
private void transformSegments(List<TextSegment> segments, AffineTransform transform)
|
||||
{
|
||||
for (TextSegment segment : segments)
|
||||
{
|
||||
if (segment.textPath != null)
|
||||
{
|
||||
segment.textPath.transform(transform);
|
||||
} else
|
||||
{
|
||||
segment.element.fullPath.transform(transform);
|
||||
segment.element.textBounds = segment.element.fullPath.getBounds2D();
|
||||
transformSegments(segment.element.segments, transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
|
||||
//Get current values for parameters
|
||||
FontUtil.FontInfo fontInfoOld = fontInfo;
|
||||
float[] xOld = x;
|
||||
float[] yOld = y;
|
||||
float[] dxOld = dx;
|
||||
float[] dyOld = dy;
|
||||
buildShapeInformation();
|
||||
|
||||
boolean shapeChange = !fontInfo.equals(fontInfoOld)
|
||||
|| !Arrays.equals(xOld, x)
|
||||
|| !Arrays.equals(yOld, y)
|
||||
|| !Arrays.equals(dxOld, dx)
|
||||
|| !Arrays.equals(dyOld, dy);
|
||||
|
||||
if (shapeChange)
|
||||
{
|
||||
buildText();
|
||||
}
|
||||
|
||||
return changeState || shapeChange;
|
||||
}
|
||||
}
|
90
graphics-svg/src/main/java/org/xbib/graphics/svg/Title.java
Normal file
90
graphics-svg/src/main/java/org/xbib/graphics/svg/Title.java
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* 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 September 19, 2004, 1:56 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
/**
|
||||
* Holds title textual information within tree
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Title extends SVGElement
|
||||
{
|
||||
public static final String TAG_NAME = "title";
|
||||
|
||||
StringBuffer text = new StringBuffer();
|
||||
|
||||
/**
|
||||
* Creates a new instance of Stop
|
||||
*/
|
||||
public Title()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during load process to add text scanned within a tag
|
||||
*/
|
||||
@Override
|
||||
public void loaderAddText(SVGLoaderHelper helper, String text)
|
||||
{
|
||||
this.text.append(text);
|
||||
}
|
||||
|
||||
public String getText()
|
||||
{
|
||||
return text.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
//Title does not change
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 9:00 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* Maintains bounding box for this element
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
abstract public class TransformableElement extends SVGElement
|
||||
{
|
||||
AffineTransform xform = null;
|
||||
|
||||
/**
|
||||
* Creates a new instance of BoundedElement
|
||||
*/
|
||||
public TransformableElement()
|
||||
{
|
||||
}
|
||||
|
||||
public TransformableElement(String id, SVGElement parent)
|
||||
{
|
||||
super(id, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a copy of the cached AffineTransform. Note that this value will
|
||||
* only be valid after the node has been updated.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public AffineTransform getXForm()
|
||||
{
|
||||
return xform == null ? null : new AffineTransform(xform);
|
||||
}
|
||||
/*
|
||||
public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent)
|
||||
{
|
||||
//Load style string
|
||||
super.loaderStartElement(helper, attrs, parent);
|
||||
|
||||
String transform = attrs.getValue("transform");
|
||||
if (transform != null)
|
||||
{
|
||||
xform = parseTransform(transform);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("transform")))
|
||||
{
|
||||
xform = parseTransform(sty.getStringValue());
|
||||
}
|
||||
}
|
||||
|
||||
protected Shape shapeToParent(Shape shape)
|
||||
{
|
||||
if (xform == null)
|
||||
{
|
||||
return shape;
|
||||
}
|
||||
return xform.createTransformedShape(shape);
|
||||
}
|
||||
|
||||
protected Rectangle2D boundsToParent(Rectangle2D rect)
|
||||
{
|
||||
if (xform == null || rect == null)
|
||||
{
|
||||
return rect;
|
||||
}
|
||||
return xform.createTransformedShape(rect).getBounds2D();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("transform")))
|
||||
{
|
||||
AffineTransform newXform = parseTransform(sty.getStringValue());
|
||||
if (!newXform.equals(xform))
|
||||
{
|
||||
xform = newXform;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
395
graphics-svg/src/main/java/org/xbib/graphics/svg/Tspan.java
Normal file
395
graphics-svg/src/main/java/org/xbib/graphics/svg/Tspan.java
Normal file
|
@ -0,0 +1,395 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 1:56 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.util.FontUtil;
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Tspan extends ShapeElement
|
||||
{
|
||||
|
||||
public static final String TAG_NAME = "tspan";
|
||||
float[] x = null;
|
||||
float[] y = null;
|
||||
float[] dx = null;
|
||||
float[] dy = null;
|
||||
float[] rotate = null;
|
||||
|
||||
float textLength = -1;
|
||||
String lengthAdjust = "spacing";
|
||||
|
||||
// List of strings and tspans containing the content of this node
|
||||
private final List<Serializable> content = new ArrayList<>();
|
||||
protected final ArrayList<TextSegment> segments = new ArrayList<>();
|
||||
protected Rectangle2D textBounds;
|
||||
protected Path2D fullPath;
|
||||
|
||||
protected FontUtil.FontInfo fontInfo;
|
||||
private Font font;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Tspan
|
||||
*/
|
||||
public Tspan()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the start element but before the end element to indicate
|
||||
* each child tag that has been processed
|
||||
*/
|
||||
@Override
|
||||
public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
|
||||
{
|
||||
super.loaderAddChild(helper, child);
|
||||
|
||||
content.add(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during load process to add text scanned within a tag
|
||||
*/
|
||||
@Override
|
||||
public void loaderAddText(SVGLoaderHelper helper, String text)
|
||||
{
|
||||
Matcher matchWs = Pattern.compile("\\s*").matcher(text);
|
||||
if (!matchWs.matches())
|
||||
{
|
||||
content.add(text);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Serializable> getContent()
|
||||
{
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all strings and Tspan elements that are children of this element.
|
||||
*/
|
||||
public void clearContent()
|
||||
{
|
||||
content.clear();
|
||||
}
|
||||
|
||||
public void appendText(String text)
|
||||
{
|
||||
content.add(text);
|
||||
}
|
||||
|
||||
public void appendTspan(Tspan tspan) throws SVGElementException
|
||||
{
|
||||
super.loaderAddChild(null, tspan);
|
||||
content.add(tspan);
|
||||
}
|
||||
|
||||
protected void buildAttributes(StyleAttribute sty) throws SVGException
|
||||
{
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
x = sty.getFloatListWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
y = sty.getFloatListWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("dx")))
|
||||
{
|
||||
dx = sty.getFloatListWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("dy")))
|
||||
{
|
||||
dy = sty.getFloatListWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("rotate")))
|
||||
{
|
||||
rotate = sty.getFloatList();
|
||||
for (int i = 0; i < this.rotate.length; i++)
|
||||
{
|
||||
rotate[i] = (float) Math.toRadians(this.rotate[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (getStyle(sty.setName("textLength")))
|
||||
{
|
||||
textLength = sty.getFloatValueWithUnits();
|
||||
}
|
||||
else
|
||||
{
|
||||
textLength = -1;
|
||||
}
|
||||
|
||||
if (getStyle(sty.setName("lengthAdjust")))
|
||||
{
|
||||
lengthAdjust = sty.getStringValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
lengthAdjust = "spacing";
|
||||
}
|
||||
}
|
||||
|
||||
protected void buildShapeInformation() throws SVGException
|
||||
{
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
buildAttributes(sty);
|
||||
|
||||
fontInfo = FontUtil.parseFontInfo(this, sty);
|
||||
font = FontUtil.getFont(fontInfo, diagram);
|
||||
}
|
||||
|
||||
protected void buildTextShape(Cursor cursor) throws SVGException
|
||||
{
|
||||
buildShapeInformation();
|
||||
|
||||
fullPath = new GeneralPath();
|
||||
|
||||
segments.clear();
|
||||
segments.ensureCapacity(content.size());
|
||||
int currentCursorOffset = cursor.offset;
|
||||
cursor.offset = 0;
|
||||
|
||||
AffineTransform transform = new AffineTransform();
|
||||
|
||||
float spaceAdvance = font.getGlyph(" ").getHorizAdvX();
|
||||
|
||||
for (Serializable obj : content)
|
||||
{
|
||||
if (obj instanceof String)
|
||||
{
|
||||
String text = ((String) obj);
|
||||
String trimmed = text.trim();
|
||||
if (!text.isEmpty() && text.charAt(0) <= ' ')
|
||||
cursor.x += font.getGlyph(" ").getHorizAdvX();
|
||||
Path2D textPath = createStringSegmentPath(trimmed, font, cursor, transform);
|
||||
if (!text.isEmpty() && text.charAt(text.length() - 1) <= ' ')
|
||||
cursor.x += spaceAdvance;
|
||||
|
||||
fullPath.append(textPath, false);
|
||||
segments.add(new TextSegment(textPath, this));
|
||||
} else if (obj instanceof Tspan)
|
||||
{
|
||||
Tspan tspan = (Tspan) obj;
|
||||
tspan.buildTextShape(cursor);
|
||||
fullPath.append(tspan.fullPath, false);
|
||||
segments.add(new TextSegment(null, (Tspan) obj));
|
||||
}
|
||||
}
|
||||
|
||||
textBounds = fullPath.getBounds2D();
|
||||
cursor.offset += currentCursorOffset;
|
||||
}
|
||||
|
||||
private Path2D createStringSegmentPath(String text, Font font, Cursor cursor, AffineTransform xform)
|
||||
{
|
||||
Path2D textPath = new GeneralPath();
|
||||
|
||||
for (int i = 0; i < text.length(); i++)
|
||||
{
|
||||
// The positions are specified for the whole recursive content of a span.
|
||||
// We need to account for any eventual text which occurred before.
|
||||
cursor.x = getXCursorForIndex(cursor.x, cursor.offset + i);
|
||||
cursor.y = getYCursorForIndex(cursor.y, cursor.offset + i);
|
||||
|
||||
xform.setToTranslation(cursor.x, cursor.y);
|
||||
if (rotate != null && cursor.offset + i < rotate.length)
|
||||
{
|
||||
xform.rotate(rotate[cursor.offset + i]);
|
||||
}
|
||||
|
||||
String unicode = text.substring(i, i + 1);
|
||||
MissingGlyph glyph = font.getGlyph(unicode);
|
||||
|
||||
Shape path = glyph.getPath();
|
||||
if (path != null)
|
||||
{
|
||||
path = xform.createTransformedShape(path);
|
||||
textPath.append(path, false);
|
||||
}
|
||||
cursor.x += glyph.getHorizAdvX() + fontInfo.letterSpacing;
|
||||
}
|
||||
cursor.offset += text.length();
|
||||
|
||||
strokeWidthScalar = 1f;
|
||||
return textPath;
|
||||
}
|
||||
|
||||
protected Cursor createInitialCursor()
|
||||
{
|
||||
return new Cursor(getXCursorForIndex(0, 0),
|
||||
getYCursorForIndex(0, 0));
|
||||
}
|
||||
|
||||
private float getXCursorForIndex(float current, int index)
|
||||
{
|
||||
return getCursorForIndex(current, index, x, dx);
|
||||
}
|
||||
|
||||
private float getYCursorForIndex(float current, int index)
|
||||
{
|
||||
return getCursorForIndex(current, index, y, dy);
|
||||
}
|
||||
|
||||
private float getCursorForIndex(float current, int index, float[] absolutes, float[] deltas)
|
||||
{
|
||||
if (absolutes != null && index < absolutes.length)
|
||||
{
|
||||
current = absolutes[index];
|
||||
} else if (deltas != null && index < deltas.length)
|
||||
{
|
||||
current += deltas[index];
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRender(Graphics2D g) throws SVGException
|
||||
{
|
||||
beginLayer(g);
|
||||
for (TextSegment segment : segments) {
|
||||
if (segment.textPath != null)
|
||||
{
|
||||
// Text portion of this span.
|
||||
segment.element.renderShape(g, segment.textPath);
|
||||
} else
|
||||
{
|
||||
// Child span.
|
||||
segment.element.doRender(g);
|
||||
}
|
||||
}
|
||||
finishLayer(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getShape()
|
||||
{
|
||||
return shapeToParent(fullPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBoundingBox()
|
||||
{
|
||||
return boundsToParent(textBounds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
//Tspan does not change
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getText()
|
||||
{
|
||||
return getText(new StringBuilder());
|
||||
}
|
||||
|
||||
private String getText(StringBuilder builder)
|
||||
{
|
||||
for (Serializable serializable : content)
|
||||
{
|
||||
if (serializable instanceof Tspan)
|
||||
{
|
||||
((Tspan) serializable).getText(builder);
|
||||
builder.append(' ');
|
||||
} else if (serializable != null)
|
||||
{
|
||||
builder.append(serializable).append(' ');
|
||||
}
|
||||
}
|
||||
if (builder.length() > 0)
|
||||
{
|
||||
// Remove trailing space.
|
||||
return builder.substring(0, builder.length() - 1);
|
||||
} else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
protected static class TextSegment {
|
||||
final Path2D textPath;
|
||||
final Tspan element;
|
||||
|
||||
private TextSegment(Path2D textPath, Tspan element) {
|
||||
this.textPath = textPath;
|
||||
this.element = element;
|
||||
}
|
||||
}
|
||||
|
||||
protected static class Cursor {
|
||||
float x;
|
||||
float y;
|
||||
int offset;
|
||||
|
||||
public Cursor(float x, float y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
}
|
264
graphics-svg/src/main/java/org/xbib/graphics/svg/Use.java
Normal file
264
graphics-svg/src/main/java/org/xbib/graphics/svg/Use.java
Normal file
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 1:54 AM
|
||||
*/
|
||||
package org.xbib.graphics.svg;
|
||||
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Use extends ShapeElement
|
||||
{
|
||||
public static final String TAG_NAME = "use";
|
||||
|
||||
float x = 0f;
|
||||
float y = 0f;
|
||||
float width = 1f;
|
||||
float height = 1f;
|
||||
// SVGElement href = null;
|
||||
URI href = null;
|
||||
AffineTransform refXform;
|
||||
|
||||
/**
|
||||
* Creates a new instance of LinearGradient
|
||||
*/
|
||||
public Use()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName()
|
||||
{
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void build() throws SVGException
|
||||
{
|
||||
super.build();
|
||||
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
x = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
y = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("width")))
|
||||
{
|
||||
width = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("height")))
|
||||
{
|
||||
height = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("xlink:href")))
|
||||
{
|
||||
URI src = sty.getURIValue(getXMLBase());
|
||||
href = src;
|
||||
// href = diagram.getUniverse().getElement(src);
|
||||
}
|
||||
|
||||
//Determine use offset/scale
|
||||
refXform = new AffineTransform();
|
||||
refXform.translate(this.x, this.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRender(Graphics2D g) throws SVGException
|
||||
{
|
||||
beginLayer(g);
|
||||
|
||||
//AffineTransform oldXform = g.getTransform();
|
||||
AffineTransform oldXform = g.getTransform();
|
||||
g.transform(refXform);
|
||||
|
||||
SVGElement ref = diagram.getUniverse().getElement(href);
|
||||
|
||||
if (ref == null || !(ref instanceof RenderableElement))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RenderableElement rendEle = (RenderableElement)ref;
|
||||
rendEle.pushParentContext(this);
|
||||
rendEle.render(g);
|
||||
rendEle.popParentContext();
|
||||
|
||||
g.setTransform(oldXform);
|
||||
|
||||
finishLayer(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getShape()
|
||||
{
|
||||
SVGElement ref = diagram.getUniverse().getElement(href);
|
||||
if (ref instanceof ShapeElement)
|
||||
{
|
||||
Shape shape = ((ShapeElement) ref).getShape();
|
||||
shape = refXform.createTransformedShape(shape);
|
||||
shape = shapeToParent(shape);
|
||||
return shape;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBoundingBox() throws SVGException
|
||||
{
|
||||
SVGElement ref = diagram.getUniverse().getElement(href);
|
||||
if (ref instanceof ShapeElement)
|
||||
{
|
||||
ShapeElement shapeEle = (ShapeElement) ref;
|
||||
shapeEle.pushParentContext(this);
|
||||
Rectangle2D bounds = shapeEle.getBoundingBox();
|
||||
shapeEle.popParentContext();
|
||||
|
||||
bounds = refXform.createTransformedShape(bounds).getBounds2D();
|
||||
bounds = boundsToParent(bounds);
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all attributes in this diagram associated with a time event. Ie,
|
||||
* all attributes with track information.
|
||||
*
|
||||
* @return - true if this node has changed state as a result of the time
|
||||
* update
|
||||
*/
|
||||
@Override
|
||||
public boolean updateTime(double curTime) throws SVGException
|
||||
{
|
||||
// if (trackManager.getNumTracks() == 0) return false;
|
||||
boolean changeState = super.updateTime(curTime);
|
||||
|
||||
//Get current values for parameters
|
||||
StyleAttribute sty = new StyleAttribute();
|
||||
boolean shapeChange = false;
|
||||
|
||||
if (getPres(sty.setName("x")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != x)
|
||||
{
|
||||
x = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("y")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != y)
|
||||
{
|
||||
y = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("width")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != width)
|
||||
{
|
||||
width = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("height")))
|
||||
{
|
||||
float newVal = sty.getFloatValueWithUnits();
|
||||
if (newVal != height)
|
||||
{
|
||||
height = newVal;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (getPres(sty.setName("xlink:href")))
|
||||
{
|
||||
URI src = sty.getURIValue(getXMLBase());
|
||||
// SVGElement newVal = diagram.getUniverse().getElement(src);
|
||||
if (!src.equals(href))
|
||||
{
|
||||
href = src;
|
||||
shapeChange = true;
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (getPres(sty.setName("xlink:href")))
|
||||
{
|
||||
URI src = sty.getURIValue(getXMLBase());
|
||||
href = diagram.getUniverse().getElement(src);
|
||||
}
|
||||
|
||||
//Determine use offset/scale
|
||||
refXform = new AffineTransform();
|
||||
refXform.translate(this.x, this.y);
|
||||
refXform.scale(this.width, this.height);
|
||||
*/
|
||||
if (shapeChange)
|
||||
{
|
||||
build();
|
||||
//Determine use offset/scale
|
||||
// refXform.setToTranslation(this.x, this.y);
|
||||
// refXform.scale(this.width, this.height);
|
||||
// return true;
|
||||
}
|
||||
|
||||
return changeState || shapeChange;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* 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 September 6, 2004, 1:19 AM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.app;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class MainFrame extends javax.swing.JFrame
|
||||
{
|
||||
public static final long serialVersionUID = 1;
|
||||
|
||||
/** Creates new form MainFrame */
|
||||
public MainFrame()
|
||||
{
|
||||
initComponents();
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
*/
|
||||
private void initComponents()//GEN-BEGIN:initComponents
|
||||
{
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
bn_svgViewer = new javax.swing.JButton();
|
||||
bn_svgViewer1 = new javax.swing.JButton();
|
||||
jPanel2 = new javax.swing.JPanel();
|
||||
bn_quit = new javax.swing.JButton();
|
||||
|
||||
setTitle("SVG Salamander - Application Launcher");
|
||||
addWindowListener(new java.awt.event.WindowAdapter()
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(java.awt.event.WindowEvent evt)
|
||||
{
|
||||
exitForm(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, javax.swing.BoxLayout.Y_AXIS));
|
||||
|
||||
bn_svgViewer.setText("SVG Viewer (No animation)");
|
||||
bn_svgViewer.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
bn_svgViewerActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jPanel1.add(bn_svgViewer);
|
||||
|
||||
bn_svgViewer1.setText("SVG Player (Animation)");
|
||||
bn_svgViewer1.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
bn_svgViewer1ActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jPanel1.add(bn_svgViewer1);
|
||||
|
||||
getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
|
||||
|
||||
bn_quit.setText("Quit");
|
||||
bn_quit.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
bn_quitActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jPanel2.add(bn_quit);
|
||||
|
||||
getContentPane().add(jPanel2, java.awt.BorderLayout.SOUTH);
|
||||
|
||||
pack();
|
||||
}//GEN-END:initComponents
|
||||
|
||||
private void bn_svgViewer1ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_svgViewer1ActionPerformed
|
||||
{//GEN-HEADEREND:event_bn_svgViewer1ActionPerformed
|
||||
SVGPlayer.main(null);
|
||||
|
||||
close();
|
||||
}//GEN-LAST:event_bn_svgViewer1ActionPerformed
|
||||
|
||||
private void bn_svgViewerActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_svgViewerActionPerformed
|
||||
{//GEN-HEADEREND:event_bn_svgViewerActionPerformed
|
||||
SVGViewer.main(null);
|
||||
|
||||
close();
|
||||
}//GEN-LAST:event_bn_svgViewerActionPerformed
|
||||
|
||||
private void bn_quitActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_quitActionPerformed
|
||||
{//GEN-HEADEREND:event_bn_quitActionPerformed
|
||||
exitForm(null);
|
||||
}//GEN-LAST:event_bn_quitActionPerformed
|
||||
|
||||
/** Exit the Application */
|
||||
private void exitForm(java.awt.event.WindowEvent evt)//GEN-FIRST:event_exitForm
|
||||
{
|
||||
System.exit(0);
|
||||
}//GEN-LAST:event_exitForm
|
||||
|
||||
private void close()
|
||||
{
|
||||
this.setVisible(false);
|
||||
this.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String args[])
|
||||
{
|
||||
new MainFrame().setVisible(true);
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton bn_quit;
|
||||
private javax.swing.JButton bn_svgViewer;
|
||||
private javax.swing.JButton bn_svgViewer1;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JPanel jPanel2;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
}
|
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
* 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 September 28, 2004, 9:56 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.app;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class PlayerDialog extends javax.swing.JDialog implements PlayerThreadListener
|
||||
{
|
||||
public static final long serialVersionUID = 1;
|
||||
|
||||
PlayerThread thread;
|
||||
|
||||
final SVGPlayer parent;
|
||||
|
||||
/** Creates new form PlayerDialog */
|
||||
public PlayerDialog(SVGPlayer parent)
|
||||
{
|
||||
super(parent, false);
|
||||
initComponents();
|
||||
|
||||
this.parent = parent;
|
||||
|
||||
thread = new PlayerThread();
|
||||
thread.addListener(this);
|
||||
|
||||
text_timeStepActionPerformed(null);
|
||||
}
|
||||
|
||||
public void updateTime(double curTime, double timeStep, int playState)
|
||||
{
|
||||
if (playState == PlayerThread.PS_STOP) return;
|
||||
|
||||
text_curTime.setText("" + (float)curTime);
|
||||
parent.updateTime(curTime);
|
||||
// text_timeStep.setText("" + (int)(1.0 / timeStep));
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
|
||||
private void initComponents()
|
||||
{
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
bn_playBack = new javax.swing.JButton();
|
||||
bn_stop = new javax.swing.JButton();
|
||||
bn_playFwd = new javax.swing.JButton();
|
||||
jPanel2 = new javax.swing.JPanel();
|
||||
jPanel3 = new javax.swing.JPanel();
|
||||
jLabel1 = new javax.swing.JLabel();
|
||||
text_curTime = new javax.swing.JTextField();
|
||||
bn_time0 = new javax.swing.JButton();
|
||||
jPanel4 = new javax.swing.JPanel();
|
||||
jLabel2 = new javax.swing.JLabel();
|
||||
text_timeStep = new javax.swing.JTextField();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
setTitle("Player");
|
||||
addWindowListener(new java.awt.event.WindowAdapter()
|
||||
{
|
||||
@Override
|
||||
public void windowClosed(java.awt.event.WindowEvent evt)
|
||||
{
|
||||
formWindowClosed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
bn_playBack.setText("<");
|
||||
bn_playBack.setToolTipText("Play backwards");
|
||||
bn_playBack.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
bn_playBackActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jPanel1.add(bn_playBack);
|
||||
|
||||
bn_stop.setText("||");
|
||||
bn_stop.setToolTipText("Stop playback");
|
||||
bn_stop.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
bn_stopActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jPanel1.add(bn_stop);
|
||||
|
||||
bn_playFwd.setText(">");
|
||||
bn_playFwd.setToolTipText("Play Forwards");
|
||||
bn_playFwd.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
bn_playFwdActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jPanel1.add(bn_playFwd);
|
||||
|
||||
getContentPane().add(jPanel1, java.awt.BorderLayout.NORTH);
|
||||
|
||||
jPanel2.setLayout(new javax.swing.BoxLayout(jPanel2, javax.swing.BoxLayout.Y_AXIS));
|
||||
|
||||
jLabel1.setText("Cur Time");
|
||||
jPanel3.add(jLabel1);
|
||||
|
||||
text_curTime.setHorizontalAlignment(javax.swing.JTextField.LEFT);
|
||||
text_curTime.setText("0");
|
||||
text_curTime.setPreferredSize(new java.awt.Dimension(100, 21));
|
||||
text_curTime.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
text_curTimeActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
text_curTime.addFocusListener(new java.awt.event.FocusAdapter()
|
||||
{
|
||||
@Override
|
||||
public void focusLost(java.awt.event.FocusEvent evt)
|
||||
{
|
||||
text_curTimeFocusLost(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jPanel3.add(text_curTime);
|
||||
|
||||
bn_time0.setText("Time 0");
|
||||
bn_time0.setToolTipText("Reset time to first frame");
|
||||
bn_time0.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
bn_time0ActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jPanel3.add(bn_time0);
|
||||
|
||||
jPanel2.add(jPanel3);
|
||||
|
||||
jLabel2.setText("Frames Per Second");
|
||||
jPanel4.add(jLabel2);
|
||||
|
||||
text_timeStep.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
|
||||
text_timeStep.setText("60");
|
||||
text_timeStep.setPreferredSize(new java.awt.Dimension(100, 21));
|
||||
text_timeStep.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
text_timeStepActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
text_timeStep.addFocusListener(new java.awt.event.FocusAdapter()
|
||||
{
|
||||
@Override
|
||||
public void focusLost(java.awt.event.FocusEvent evt)
|
||||
{
|
||||
text_timeStepFocusLost(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jPanel4.add(text_timeStep);
|
||||
|
||||
jPanel2.add(jPanel4);
|
||||
|
||||
getContentPane().add(jPanel2, java.awt.BorderLayout.CENTER);
|
||||
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void bn_time0ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_time0ActionPerformed
|
||||
{//GEN-HEADEREND:event_bn_time0ActionPerformed
|
||||
thread.setCurTime(0);
|
||||
}//GEN-LAST:event_bn_time0ActionPerformed
|
||||
|
||||
private void bn_playFwdActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_playFwdActionPerformed
|
||||
{//GEN-HEADEREND:event_bn_playFwdActionPerformed
|
||||
thread.setPlayState(PlayerThread.PS_PLAY_FWD);
|
||||
}//GEN-LAST:event_bn_playFwdActionPerformed
|
||||
|
||||
private void bn_stopActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_stopActionPerformed
|
||||
{//GEN-HEADEREND:event_bn_stopActionPerformed
|
||||
thread.setPlayState(PlayerThread.PS_STOP);
|
||||
}//GEN-LAST:event_bn_stopActionPerformed
|
||||
|
||||
private void bn_playBackActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_playBackActionPerformed
|
||||
{//GEN-HEADEREND:event_bn_playBackActionPerformed
|
||||
thread.setPlayState(PlayerThread.PS_PLAY_BACK);
|
||||
}//GEN-LAST:event_bn_playBackActionPerformed
|
||||
|
||||
private void formWindowClosed(java.awt.event.WindowEvent evt)//GEN-FIRST:event_formWindowClosed
|
||||
{//GEN-HEADEREND:event_formWindowClosed
|
||||
// thread.exit();
|
||||
}//GEN-LAST:event_formWindowClosed
|
||||
|
||||
private void text_timeStepFocusLost(java.awt.event.FocusEvent evt)//GEN-FIRST:event_text_timeStepFocusLost
|
||||
{//GEN-HEADEREND:event_text_timeStepFocusLost
|
||||
text_timeStepActionPerformed(null);
|
||||
}//GEN-LAST:event_text_timeStepFocusLost
|
||||
|
||||
private void text_timeStepActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_text_timeStepActionPerformed
|
||||
{//GEN-HEADEREND:event_text_timeStepActionPerformed
|
||||
try
|
||||
{
|
||||
int val = Integer.parseInt(text_timeStep.getText());
|
||||
thread.setTimeStep(1.0 / val);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
|
||||
double d = thread.getTimeStep();
|
||||
String newStrn = "" + (int)(1f / d);
|
||||
if (newStrn.equals(text_timeStep.getText())) return;
|
||||
text_timeStep.setText(newStrn);
|
||||
|
||||
// text_timeStepActionPerformed(null);
|
||||
}//GEN-LAST:event_text_timeStepActionPerformed
|
||||
|
||||
private void text_curTimeActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_text_curTimeActionPerformed
|
||||
{//GEN-HEADEREND:event_text_curTimeActionPerformed
|
||||
try
|
||||
{
|
||||
double val = Double.parseDouble(text_curTime.getText());
|
||||
thread.setCurTime(val);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
|
||||
double d = thread.getCurTime();
|
||||
text_curTime.setText("" + (float)d);
|
||||
|
||||
text_timeStepActionPerformed(null);
|
||||
}//GEN-LAST:event_text_curTimeActionPerformed
|
||||
|
||||
private void text_curTimeFocusLost(java.awt.event.FocusEvent evt)//GEN-FIRST:event_text_curTimeFocusLost
|
||||
{//GEN-HEADEREND:event_text_curTimeFocusLost
|
||||
text_curTimeActionPerformed(null);
|
||||
}//GEN-LAST:event_text_curTimeFocusLost
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton bn_playBack;
|
||||
private javax.swing.JButton bn_playFwd;
|
||||
private javax.swing.JButton bn_stop;
|
||||
private javax.swing.JButton bn_time0;
|
||||
private javax.swing.JLabel jLabel1;
|
||||
private javax.swing.JLabel jLabel2;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JPanel jPanel2;
|
||||
private javax.swing.JPanel jPanel3;
|
||||
private javax.swing.JPanel jPanel4;
|
||||
private javax.swing.JTextField text_curTime;
|
||||
private javax.swing.JTextField text_timeStep;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* 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 September 28, 2004, 10:07 PM
|
||||
*/
|
||||
|
||||
|
||||
package org.xbib.graphics.svg.app;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class PlayerThread implements Runnable
|
||||
{
|
||||
HashSet<PlayerThreadListener> listeners = new HashSet<PlayerThreadListener>();
|
||||
|
||||
double curTime = 0;
|
||||
double timeStep = .2;
|
||||
|
||||
public static final int PS_STOP = 0;
|
||||
public static final int PS_PLAY_FWD = 1;
|
||||
public static final int PS_PLAY_BACK = 2;
|
||||
|
||||
int playState = PS_STOP;
|
||||
|
||||
Thread thread;
|
||||
|
||||
/** Creates a new instance of PlayerThread */
|
||||
public PlayerThread()
|
||||
{
|
||||
thread = new Thread(this);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
while (thread != null)
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
switch (playState)
|
||||
{
|
||||
case PS_PLAY_FWD:
|
||||
curTime += timeStep;
|
||||
break;
|
||||
case PS_PLAY_BACK:
|
||||
curTime -= timeStep;
|
||||
if (curTime < 0) curTime = 0;
|
||||
break;
|
||||
default:
|
||||
case PS_STOP:
|
||||
break;
|
||||
}
|
||||
|
||||
fireTimeUpdateEvent();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Thread.sleep((long)(timeStep * 1000));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void exit() { thread = null; }
|
||||
public synchronized void addListener(PlayerThreadListener listener)
|
||||
{
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public synchronized double getCurTime() { return curTime; }
|
||||
|
||||
public synchronized void setCurTime(double time)
|
||||
{
|
||||
curTime = time;
|
||||
}
|
||||
|
||||
public synchronized double getTimeStep() { return timeStep; }
|
||||
|
||||
public synchronized void setTimeStep(double time)
|
||||
{
|
||||
timeStep = time;
|
||||
if (timeStep < .01) timeStep = .01;
|
||||
}
|
||||
|
||||
public synchronized int getPlayState() { return playState; }
|
||||
|
||||
public synchronized void setPlayState(int playState)
|
||||
{
|
||||
this.playState = playState;
|
||||
}
|
||||
|
||||
private void fireTimeUpdateEvent()
|
||||
{
|
||||
for (PlayerThreadListener listener : listeners) {
|
||||
listener.updateTime(curTime, timeStep, playState);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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 September 28, 2004, 10:15 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.app;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public interface PlayerThreadListener
|
||||
{
|
||||
public void updateTime(double curTime, double timeStep, int playState);
|
||||
}
|
|
@ -0,0 +1,450 @@
|
|||
/*
|
||||
* 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 April 3, 2004, 5:28 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.app;
|
||||
|
||||
|
||||
import org.xbib.graphics.svg.SVGConst;
|
||||
import org.xbib.graphics.svg.SVGDiagram;
|
||||
import org.xbib.graphics.svg.SVGDisplayPanel;
|
||||
import org.xbib.graphics.svg.SVGElement;
|
||||
import org.xbib.graphics.svg.SVGException;
|
||||
import org.xbib.graphics.svg.SVGUniverse;
|
||||
import java.awt.Color;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.security.AccessControlException;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class SVGPlayer extends javax.swing.JFrame
|
||||
{
|
||||
public static final long serialVersionUID = 1;
|
||||
|
||||
SVGDisplayPanel svgDisplayPanel = new SVGDisplayPanel();
|
||||
|
||||
final PlayerDialog playerDialog;
|
||||
|
||||
SVGUniverse universe;
|
||||
|
||||
/** FileChooser for running in trusted environments */
|
||||
final JFileChooser fileChooser;
|
||||
{
|
||||
// fileChooser = new JFileChooser(new File("."));
|
||||
JFileChooser fc = null;
|
||||
try
|
||||
{
|
||||
fc = new JFileChooser();
|
||||
fc.setFileFilter(
|
||||
new javax.swing.filechooser.FileFilter() {
|
||||
final Matcher matchLevelFile = Pattern.compile(".*\\.svg[z]?").matcher("");
|
||||
|
||||
@Override
|
||||
public boolean accept(File file)
|
||||
{
|
||||
if (file.isDirectory()) return true;
|
||||
|
||||
matchLevelFile.reset(file.getName());
|
||||
return matchLevelFile.matches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() { return "SVG file (*.svg, *.svgz)"; }
|
||||
}
|
||||
);
|
||||
}
|
||||
catch (AccessControlException ex)
|
||||
{
|
||||
//Do not create file chooser if webstart refuses permissions
|
||||
}
|
||||
fileChooser = fc;
|
||||
}
|
||||
|
||||
/** Backup file service for opening files in WebStart situations */
|
||||
/*
|
||||
final FileOpenService fileOpenService;
|
||||
{
|
||||
try
|
||||
{
|
||||
fileOpenService = (FileOpenService)ServiceManager.lookup("javax.jnlp.FileOpenService");
|
||||
}
|
||||
catch (UnavailableServiceException e)
|
||||
{
|
||||
fileOpenService = null;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/** Creates new form SVGViewer */
|
||||
public SVGPlayer() {
|
||||
initComponents();
|
||||
|
||||
setSize(800, 600);
|
||||
|
||||
svgDisplayPanel.setBgColor(Color.white);
|
||||
svgDisplayPanel.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent evt)
|
||||
{
|
||||
SVGDiagram diagram = svgDisplayPanel.getDiagram();
|
||||
if (diagram == null) return;
|
||||
|
||||
System.out.println("Picking at cursor (" + evt.getX() + ", " + evt.getY() + ")");
|
||||
try
|
||||
{
|
||||
List<List<SVGElement>> paths = diagram.pick(new Point2D.Float(evt.getX(), evt.getY()), null);
|
||||
for (int i = 0; i < paths.size(); i++)
|
||||
{
|
||||
System.out.println(pathToString(paths.get(i)));
|
||||
}
|
||||
}
|
||||
catch (SVGException ex)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
|
||||
"Could not pick", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
svgDisplayPanel.setPreferredSize(getSize());
|
||||
scrollPane_svgArea.setViewportView(svgDisplayPanel);
|
||||
|
||||
playerDialog = new PlayerDialog(this);
|
||||
}
|
||||
|
||||
private String pathToString(List<SVGElement> path)
|
||||
{
|
||||
if (path.size() == 0) return "";
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(path.get(0));
|
||||
for (int i = 1; i < path.size(); i++)
|
||||
{
|
||||
sb.append("/");
|
||||
sb.append(path.get(i).getId());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void updateTime(double curTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (universe != null)
|
||||
{
|
||||
universe.setCurTime(curTime);
|
||||
universe.updateTime();
|
||||
// svgDisplayPanel.updateTime(curTime);
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadURL(URL url)
|
||||
{
|
||||
boolean verbose = cmCheck_verbose.isSelected();
|
||||
|
||||
universe = new SVGUniverse();
|
||||
universe.setVerbose(verbose);
|
||||
SVGDiagram diagram = null;
|
||||
|
||||
if (!CheckBoxMenuItem_anonInputStream.isSelected())
|
||||
{
|
||||
//Load from a disk with a valid URL
|
||||
URI uri = universe.loadSVG(url);
|
||||
|
||||
if (verbose) System.err.println(uri.toString());
|
||||
|
||||
diagram = universe.getDiagram(uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Load from a stream with no particular valid URL
|
||||
try
|
||||
{
|
||||
InputStream is = url.openStream();
|
||||
URI uri = universe.loadSVG(is, "defaultName");
|
||||
|
||||
if (verbose) System.err.println(uri.toString());
|
||||
|
||||
diagram = universe.getDiagram(uri);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e);
|
||||
}
|
||||
}
|
||||
|
||||
svgDisplayPanel.setDiagram(diagram);
|
||||
repaint();
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
|
||||
private void initComponents()
|
||||
{
|
||||
scrollPane_svgArea = new javax.swing.JScrollPane();
|
||||
jMenuBar1 = new javax.swing.JMenuBar();
|
||||
menu_file = new javax.swing.JMenu();
|
||||
cm_loadFile = new javax.swing.JMenuItem();
|
||||
cm_loadUrl = new javax.swing.JMenuItem();
|
||||
menu_window = new javax.swing.JMenu();
|
||||
cm_player = new javax.swing.JMenuItem();
|
||||
jSeparator2 = new javax.swing.JSeparator();
|
||||
cm_800x600 = new javax.swing.JMenuItem();
|
||||
CheckBoxMenuItem_anonInputStream = new javax.swing.JCheckBoxMenuItem();
|
||||
cmCheck_verbose = new javax.swing.JCheckBoxMenuItem();
|
||||
menu_help = new javax.swing.JMenu();
|
||||
cm_about = new javax.swing.JMenuItem();
|
||||
|
||||
setTitle("SVG Player - Salamander Project");
|
||||
addWindowListener(new java.awt.event.WindowAdapter()
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(java.awt.event.WindowEvent evt)
|
||||
{
|
||||
exitForm(evt);
|
||||
}
|
||||
});
|
||||
|
||||
getContentPane().add(scrollPane_svgArea, java.awt.BorderLayout.CENTER);
|
||||
|
||||
menu_file.setMnemonic('f');
|
||||
menu_file.setText("File");
|
||||
cm_loadFile.setMnemonic('l');
|
||||
cm_loadFile.setText("Load File...");
|
||||
cm_loadFile.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
cm_loadFileActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
menu_file.add(cm_loadFile);
|
||||
|
||||
cm_loadUrl.setText("Load URL...");
|
||||
cm_loadUrl.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
cm_loadUrlActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
menu_file.add(cm_loadUrl);
|
||||
|
||||
jMenuBar1.add(menu_file);
|
||||
|
||||
menu_window.setText("Window");
|
||||
cm_player.setText("Player");
|
||||
cm_player.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
cm_playerActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
menu_window.add(cm_player);
|
||||
|
||||
menu_window.add(jSeparator2);
|
||||
|
||||
cm_800x600.setText("800 x 600");
|
||||
cm_800x600.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
cm_800x600ActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
menu_window.add(cm_800x600);
|
||||
|
||||
CheckBoxMenuItem_anonInputStream.setText("Anonymous Input Stream");
|
||||
menu_window.add(CheckBoxMenuItem_anonInputStream);
|
||||
|
||||
cmCheck_verbose.setText("Verbose");
|
||||
cmCheck_verbose.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
cmCheck_verboseActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
menu_window.add(cmCheck_verbose);
|
||||
|
||||
jMenuBar1.add(menu_window);
|
||||
|
||||
menu_help.setText("Help");
|
||||
cm_about.setText("About...");
|
||||
cm_about.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
cm_aboutActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
menu_help.add(cm_about);
|
||||
|
||||
jMenuBar1.add(menu_help);
|
||||
|
||||
setJMenuBar(jMenuBar1);
|
||||
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void cm_loadUrlActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadUrlActionPerformed
|
||||
{//GEN-HEADEREND:event_cm_loadUrlActionPerformed
|
||||
String urlStrn = JOptionPane.showInputDialog(this, "Enter URL of SVG file");
|
||||
if (urlStrn == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
URL url = new URL(URLEncoder.encode(urlStrn, "UTF-8"));
|
||||
loadURL(url);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e);
|
||||
}
|
||||
|
||||
}//GEN-LAST:event_cm_loadUrlActionPerformed
|
||||
|
||||
private void cmCheck_verboseActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cmCheck_verboseActionPerformed
|
||||
{//GEN-HEADEREND:event_cmCheck_verboseActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cmCheck_verboseActionPerformed
|
||||
|
||||
private void cm_playerActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_playerActionPerformed
|
||||
{//GEN-HEADEREND:event_cm_playerActionPerformed
|
||||
playerDialog.setVisible(true);
|
||||
}//GEN-LAST:event_cm_playerActionPerformed
|
||||
|
||||
private void cm_aboutActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_aboutActionPerformed
|
||||
{//GEN-HEADEREND:event_cm_aboutActionPerformed
|
||||
VersionDialog dia = new VersionDialog(this, true, cmCheck_verbose.isSelected());
|
||||
dia.setVisible(true);
|
||||
// JOptionPane.showMessageDialog(this, "Salamander SVG - Created by Mark McKay\nhttp://www.kitfox.com");
|
||||
}//GEN-LAST:event_cm_aboutActionPerformed
|
||||
|
||||
private void cm_800x600ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cm_800x600ActionPerformed
|
||||
setSize(800, 600);
|
||||
}//GEN-LAST:event_cm_800x600ActionPerformed
|
||||
|
||||
private void cm_loadFileActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadFileActionPerformed
|
||||
{//GEN-HEADEREND:event_cm_loadFileActionPerformed
|
||||
boolean verbose = cmCheck_verbose.isSelected();
|
||||
|
||||
try
|
||||
{
|
||||
int retVal = fileChooser.showOpenDialog(this);
|
||||
if (retVal == JFileChooser.APPROVE_OPTION)
|
||||
{
|
||||
File chosenFile = fileChooser.getSelectedFile();
|
||||
|
||||
URL url = chosenFile.toURI().toURL();
|
||||
|
||||
loadURL(url);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e);
|
||||
}
|
||||
|
||||
}//GEN-LAST:event_cm_loadFileActionPerformed
|
||||
|
||||
/** Exit the Application */
|
||||
private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm
|
||||
System.exit(0);
|
||||
}//GEN-LAST:event_exitForm
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
new SVGPlayer().setVisible(true);
|
||||
}
|
||||
|
||||
public void updateTime(double curTime, double timeStep, int playState)
|
||||
{
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JCheckBoxMenuItem CheckBoxMenuItem_anonInputStream;
|
||||
private javax.swing.JCheckBoxMenuItem cmCheck_verbose;
|
||||
private javax.swing.JMenuItem cm_800x600;
|
||||
private javax.swing.JMenuItem cm_about;
|
||||
private javax.swing.JMenuItem cm_loadFile;
|
||||
private javax.swing.JMenuItem cm_loadUrl;
|
||||
private javax.swing.JMenuItem cm_player;
|
||||
private javax.swing.JMenuBar jMenuBar1;
|
||||
private javax.swing.JSeparator jSeparator2;
|
||||
private javax.swing.JMenu menu_file;
|
||||
private javax.swing.JMenu menu_help;
|
||||
private javax.swing.JMenu menu_window;
|
||||
private javax.swing.JScrollPane scrollPane_svgArea;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
}
|
|
@ -0,0 +1,425 @@
|
|||
/*
|
||||
* 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 April 3, 2004, 5:28 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.app;
|
||||
|
||||
import org.xbib.graphics.svg.SVGCache;
|
||||
import org.xbib.graphics.svg.SVGConst;
|
||||
import org.xbib.graphics.svg.SVGDiagram;
|
||||
import org.xbib.graphics.svg.SVGDisplayPanel;
|
||||
import org.xbib.graphics.svg.SVGElement;
|
||||
import org.xbib.graphics.svg.SVGException;
|
||||
import org.xbib.graphics.svg.SVGUniverse;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Point;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.security.AccessControlException;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class SVGViewer extends javax.swing.JFrame
|
||||
{
|
||||
public static final long serialVersionUID = 1;
|
||||
|
||||
SVGDisplayPanel svgDisplayPanel = new SVGDisplayPanel();
|
||||
|
||||
/** FileChooser for running in trusted environments */
|
||||
final JFileChooser fileChooser;
|
||||
{
|
||||
// fileChooser = new JFileChooser(new File("."));
|
||||
JFileChooser fc = null;
|
||||
try
|
||||
{
|
||||
fc = new JFileChooser();
|
||||
fc.setFileFilter(
|
||||
new javax.swing.filechooser.FileFilter() {
|
||||
final Matcher matchLevelFile = Pattern.compile(".*\\.svg[z]?").matcher("");
|
||||
|
||||
@Override
|
||||
public boolean accept(File file)
|
||||
{
|
||||
if (file.isDirectory()) return true;
|
||||
|
||||
matchLevelFile.reset(file.getName());
|
||||
return matchLevelFile.matches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() { return "SVG file (*.svg, *.svgz)"; }
|
||||
}
|
||||
);
|
||||
}
|
||||
catch (AccessControlException ex)
|
||||
{
|
||||
//Do not create file chooser if webstart refuses permissions
|
||||
}
|
||||
fileChooser = fc;
|
||||
}
|
||||
|
||||
/** Backup file service for opening files in WebStart situations */
|
||||
/*
|
||||
final FileOpenService fileOpenService;
|
||||
{
|
||||
try
|
||||
{
|
||||
fileOpenService = (FileOpenService)ServiceManager.lookup("javax.jnlp.FileOpenService");
|
||||
}
|
||||
catch (UnavailableServiceException e)
|
||||
{
|
||||
fileOpenService = null;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/** Creates new form SVGViewer */
|
||||
public SVGViewer() {
|
||||
initComponents();
|
||||
|
||||
setSize(800, 600);
|
||||
|
||||
svgDisplayPanel.setBgColor(Color.white);
|
||||
|
||||
svgDisplayPanel.setPreferredSize(getSize());
|
||||
panel_svgArea.add(svgDisplayPanel, BorderLayout.CENTER);
|
||||
// scrollPane_svgArea.setViewportView(svgDisplayPanel);
|
||||
}
|
||||
|
||||
private void loadURL(URL url)
|
||||
{
|
||||
boolean verbose = cmCheck_verbose.isSelected();
|
||||
|
||||
// SVGUniverse universe = new SVGUniverse();
|
||||
SVGUniverse universe = SVGCache.getSVGUniverse();
|
||||
SVGDiagram diagram = null;
|
||||
URI uri;
|
||||
|
||||
if (!CheckBoxMenuItem_anonInputStream.isSelected())
|
||||
{
|
||||
//Load from a disk with a valid URL
|
||||
uri = universe.loadSVG(url);
|
||||
|
||||
if (verbose) System.err.println("Loading document " + uri.toString());
|
||||
|
||||
diagram = universe.getDiagram(uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Load from a stream with no particular valid URL
|
||||
try
|
||||
{
|
||||
InputStream is = url.openStream();
|
||||
uri = universe.loadSVG(is, "defaultName");
|
||||
|
||||
if (verbose) System.err.println("Loading document " + uri.toString());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*
|
||||
ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
||||
ObjectOutputStream os = new ObjectOutputStream(bs);
|
||||
os.writeObject(universe);
|
||||
os.close();
|
||||
|
||||
ByteArrayInputStream bin = new ByteArrayInputStream(bs.toByteArray());
|
||||
ObjectInputStream is = new ObjectInputStream(bin);
|
||||
universe = (SVGUniverse)is.readObject();
|
||||
is.close();
|
||||
*/
|
||||
|
||||
diagram = universe.getDiagram(uri);
|
||||
|
||||
svgDisplayPanel.setDiagram(diagram);
|
||||
repaint();
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
|
||||
private void initComponents()
|
||||
{
|
||||
scrollPane_svgArea = new javax.swing.JScrollPane();
|
||||
panel_svgArea = new javax.swing.JPanel();
|
||||
jMenuBar1 = new javax.swing.JMenuBar();
|
||||
menu_file = new javax.swing.JMenu();
|
||||
cm_loadFile = new javax.swing.JMenuItem();
|
||||
cm_loadUrl = new javax.swing.JMenuItem();
|
||||
menu_window = new javax.swing.JMenu();
|
||||
cm_800x600 = new javax.swing.JMenuItem();
|
||||
CheckBoxMenuItem_anonInputStream = new javax.swing.JCheckBoxMenuItem();
|
||||
cmCheck_verbose = new javax.swing.JCheckBoxMenuItem();
|
||||
menu_help = new javax.swing.JMenu();
|
||||
cm_about = new javax.swing.JMenuItem();
|
||||
|
||||
setTitle("SVG Viewer - Salamander Project");
|
||||
addWindowListener(new java.awt.event.WindowAdapter()
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(java.awt.event.WindowEvent evt)
|
||||
{
|
||||
exitForm(evt);
|
||||
}
|
||||
});
|
||||
|
||||
panel_svgArea.setLayout(new java.awt.BorderLayout());
|
||||
|
||||
panel_svgArea.addMouseListener(new java.awt.event.MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mousePressed(java.awt.event.MouseEvent evt)
|
||||
{
|
||||
panel_svgAreaMousePressed(evt);
|
||||
}
|
||||
@Override
|
||||
public void mouseReleased(java.awt.event.MouseEvent evt)
|
||||
{
|
||||
panel_svgAreaMouseReleased(evt);
|
||||
}
|
||||
});
|
||||
|
||||
scrollPane_svgArea.setViewportView(panel_svgArea);
|
||||
|
||||
getContentPane().add(scrollPane_svgArea, java.awt.BorderLayout.CENTER);
|
||||
|
||||
menu_file.setMnemonic('f');
|
||||
menu_file.setText("File");
|
||||
cm_loadFile.setMnemonic('l');
|
||||
cm_loadFile.setText("Load File...");
|
||||
cm_loadFile.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
cm_loadFileActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
menu_file.add(cm_loadFile);
|
||||
|
||||
cm_loadUrl.setText("Load URL...");
|
||||
cm_loadUrl.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
cm_loadUrlActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
menu_file.add(cm_loadUrl);
|
||||
|
||||
jMenuBar1.add(menu_file);
|
||||
|
||||
menu_window.setText("Window");
|
||||
cm_800x600.setText("800 x 600");
|
||||
cm_800x600.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
cm_800x600ActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
menu_window.add(cm_800x600);
|
||||
|
||||
CheckBoxMenuItem_anonInputStream.setText("Anonymous Input Stream");
|
||||
menu_window.add(CheckBoxMenuItem_anonInputStream);
|
||||
|
||||
cmCheck_verbose.setText("Verbose");
|
||||
cmCheck_verbose.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
cmCheck_verboseActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
menu_window.add(cmCheck_verbose);
|
||||
|
||||
jMenuBar1.add(menu_window);
|
||||
|
||||
menu_help.setText("Help");
|
||||
cm_about.setText("About...");
|
||||
cm_about.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
cm_aboutActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
menu_help.add(cm_about);
|
||||
|
||||
jMenuBar1.add(menu_help);
|
||||
|
||||
setJMenuBar(jMenuBar1);
|
||||
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void cm_loadUrlActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadUrlActionPerformed
|
||||
{//GEN-HEADEREND:event_cm_loadUrlActionPerformed
|
||||
String urlStrn = JOptionPane.showInputDialog(this, "Enter URL of SVG file");
|
||||
if (urlStrn == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
URL url = new URL(URLEncoder.encode(urlStrn, "UTF-8"));
|
||||
loadURL(url);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e);
|
||||
}
|
||||
|
||||
}//GEN-LAST:event_cm_loadUrlActionPerformed
|
||||
|
||||
private void panel_svgAreaMouseReleased(java.awt.event.MouseEvent evt)//GEN-FIRST:event_panel_svgAreaMouseReleased
|
||||
{//GEN-HEADEREND:event_panel_svgAreaMouseReleased
|
||||
SVGDiagram diagram = svgDisplayPanel.getDiagram();
|
||||
List<List<SVGElement>> pickedElements;
|
||||
try
|
||||
{
|
||||
pickedElements = diagram.pick(new Point(evt.getX(), evt.getY()), null);
|
||||
}
|
||||
catch (SVGException e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e);
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("Pick results:");
|
||||
for (List<SVGElement> path : pickedElements) {
|
||||
System.out.print(" Path: ");
|
||||
|
||||
for (SVGElement ele : path) {
|
||||
System.out.print("" + ele.getId() + "(" + ele.getClass().getName() + ") ");
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}//GEN-LAST:event_panel_svgAreaMouseReleased
|
||||
|
||||
private void panel_svgAreaMousePressed(java.awt.event.MouseEvent evt)//GEN-FIRST:event_panel_svgAreaMousePressed
|
||||
{//GEN-HEADEREND:event_panel_svgAreaMousePressed
|
||||
|
||||
}//GEN-LAST:event_panel_svgAreaMousePressed
|
||||
|
||||
private void cmCheck_verboseActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cmCheck_verboseActionPerformed
|
||||
{//GEN-HEADEREND:event_cmCheck_verboseActionPerformed
|
||||
SVGCache.getSVGUniverse().setVerbose(cmCheck_verbose.isSelected());
|
||||
}//GEN-LAST:event_cmCheck_verboseActionPerformed
|
||||
|
||||
private void cm_aboutActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_aboutActionPerformed
|
||||
{//GEN-HEADEREND:event_cm_aboutActionPerformed
|
||||
//JOptionPane.showMessageDialog(this, "Salamander SVG - Created by Mark McKay\nhttp://www.kitfox.com");
|
||||
VersionDialog dlg = new VersionDialog(this, true, cmCheck_verbose.isSelected());
|
||||
dlg.setVisible(true);
|
||||
}//GEN-LAST:event_cm_aboutActionPerformed
|
||||
|
||||
private void cm_800x600ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cm_800x600ActionPerformed
|
||||
setSize(800, 600);
|
||||
}//GEN-LAST:event_cm_800x600ActionPerformed
|
||||
|
||||
private void cm_loadFileActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadFileActionPerformed
|
||||
{//GEN-HEADEREND:event_cm_loadFileActionPerformed
|
||||
try
|
||||
{
|
||||
int retVal = fileChooser.showOpenDialog(this);
|
||||
if (retVal == JFileChooser.APPROVE_OPTION)
|
||||
{
|
||||
File chosenFile = fileChooser.getSelectedFile();
|
||||
|
||||
URL url = chosenFile.toURI().toURL();
|
||||
|
||||
loadURL(url);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e);
|
||||
}
|
||||
|
||||
}//GEN-LAST:event_cm_loadFileActionPerformed
|
||||
|
||||
/** Exit the Application */
|
||||
private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm
|
||||
// setVisible(false);
|
||||
// dispose();
|
||||
System.exit(0);
|
||||
}//GEN-LAST:event_exitForm
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
new SVGViewer().setVisible(true);
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JCheckBoxMenuItem CheckBoxMenuItem_anonInputStream;
|
||||
private javax.swing.JCheckBoxMenuItem cmCheck_verbose;
|
||||
private javax.swing.JMenuItem cm_800x600;
|
||||
private javax.swing.JMenuItem cm_about;
|
||||
private javax.swing.JMenuItem cm_loadFile;
|
||||
private javax.swing.JMenuItem cm_loadUrl;
|
||||
private javax.swing.JMenuBar jMenuBar1;
|
||||
private javax.swing.JMenu menu_file;
|
||||
private javax.swing.JMenu menu_help;
|
||||
private javax.swing.JMenu menu_window;
|
||||
private javax.swing.JPanel panel_svgArea;
|
||||
private javax.swing.JScrollPane scrollPane_svgArea;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* 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 January 13, 2005, 7:23 AM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.app;
|
||||
|
||||
import org.xbib.graphics.svg.SVGConst;
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class VersionDialog extends javax.swing.JDialog
|
||||
{
|
||||
public static final long serialVersionUID = 1;
|
||||
|
||||
final boolean verbose;
|
||||
|
||||
/** Creates new form VersionDialog */
|
||||
public VersionDialog(java.awt.Frame parent, boolean modal, boolean verbose)
|
||||
{
|
||||
super(parent, modal);
|
||||
initComponents();
|
||||
|
||||
this.verbose = verbose;
|
||||
|
||||
textpane_text.setContentType("text/html");
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
try
|
||||
{
|
||||
URL url = getClass().getResource("/res/help/about/about.html");
|
||||
if (verbose)
|
||||
{
|
||||
System.err.println("" + getClass() + " trying to load about html " + url);
|
||||
}
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
|
||||
while (true)
|
||||
{
|
||||
String line = reader.readLine();
|
||||
if (line == null) break;
|
||||
sb.append(line);
|
||||
}
|
||||
|
||||
textpane_text.setText(sb.toString());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
|
||||
private void initComponents()
|
||||
{
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
textpane_text = new javax.swing.JTextPane();
|
||||
jPanel2 = new javax.swing.JPanel();
|
||||
bn_close = new javax.swing.JButton();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
setTitle("About SVG Salamander");
|
||||
jPanel1.setLayout(new java.awt.BorderLayout());
|
||||
|
||||
textpane_text.setEditable(false);
|
||||
textpane_text.setPreferredSize(new java.awt.Dimension(400, 300));
|
||||
jPanel1.add(textpane_text, java.awt.BorderLayout.CENTER);
|
||||
|
||||
getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
|
||||
|
||||
bn_close.setText("Close");
|
||||
bn_close.addActionListener(new java.awt.event.ActionListener()
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt)
|
||||
{
|
||||
bn_closeActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jPanel2.add(bn_close);
|
||||
|
||||
getContentPane().add(jPanel2, java.awt.BorderLayout.SOUTH);
|
||||
|
||||
pack();
|
||||
}
|
||||
// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void bn_closeActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_bn_closeActionPerformed
|
||||
{//GEN-HEADEREND:event_bn_closeActionPerformed
|
||||
setVisible(false);
|
||||
dispose();
|
||||
}//GEN-LAST:event_bn_closeActionPerformed
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String args[])
|
||||
{
|
||||
java.awt.EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
new VersionDialog(new javax.swing.JFrame(), true, true).setVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton bn_close;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JPanel jPanel2;
|
||||
private javax.swing.JTextPane textpane_text;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<Events>
|
||||
<EventHandler event="componentResized" listener="java.awt.event.ComponentListener" parameters="java.awt.event.ComponentEvent" handler="formComponentResized"/>
|
||||
<EventHandler event="componentShown" listener="java.awt.event.ComponentListener" parameters="java.awt.event.ComponentEvent" handler="formComponentShown"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
|
||||
<Property name="useNullLayout" type="boolean" value="true"/>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="jPanel1">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="80" y="90" width="280" height="160"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* 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 7, 2005, 4:15 AM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.app.beans;
|
||||
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* Panel based on the null layout. Allows editing with absolute layout. When
|
||||
* instanced, records layout dimensions of all subcomponents. Then, if the
|
||||
* panel is ever resized, scales all children to fit new size.
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class ProportionalLayoutPanel extends javax.swing.JPanel
|
||||
{
|
||||
public static final long serialVersionUID = 1;
|
||||
|
||||
//Margins to leave on sides of panel, expressed in fractions [0 1]
|
||||
float topMargin;
|
||||
float bottomMargin;
|
||||
float leftMargin;
|
||||
float rightMargin;
|
||||
|
||||
/** Creates new form ProportionalLayoutPanel */
|
||||
public ProportionalLayoutPanel()
|
||||
{
|
||||
initComponents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNotify()
|
||||
{
|
||||
super.addNotify();
|
||||
|
||||
Rectangle rect = this.getBounds();
|
||||
JOptionPane.showMessageDialog(this, "" + rect);
|
||||
}
|
||||
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
|
||||
private void initComponents()
|
||||
{
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
|
||||
setLayout(null);
|
||||
|
||||
addComponentListener(new java.awt.event.ComponentAdapter()
|
||||
{
|
||||
@Override
|
||||
public void componentResized(java.awt.event.ComponentEvent evt)
|
||||
{
|
||||
formComponentResized(evt);
|
||||
}
|
||||
@Override
|
||||
public void componentShown(java.awt.event.ComponentEvent evt)
|
||||
{
|
||||
formComponentShown(evt);
|
||||
}
|
||||
});
|
||||
|
||||
add(jPanel1);
|
||||
jPanel1.setBounds(80, 90, 280, 160);
|
||||
|
||||
}
|
||||
// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void formComponentShown(java.awt.event.ComponentEvent evt)//GEN-FIRST:event_formComponentShown
|
||||
{//GEN-HEADEREND:event_formComponentShown
|
||||
JOptionPane.showMessageDialog(this, "" + getWidth() + ", " + getHeight());
|
||||
|
||||
}//GEN-LAST:event_formComponentShown
|
||||
|
||||
private void formComponentResized(java.awt.event.ComponentEvent evt)//GEN-FIRST:event_formComponentResized
|
||||
{//GEN-HEADEREND:event_formComponentResized
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_formComponentResized
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JPanel jPanel1;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
}
|
|
@ -0,0 +1,556 @@
|
|||
/*
|
||||
* 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 April 21, 2005, 10:45 AM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.app.beans;
|
||||
|
||||
import org.xbib.graphics.svg.SVGCache;
|
||||
import org.xbib.graphics.svg.SVGDiagram;
|
||||
import org.xbib.graphics.svg.SVGException;
|
||||
import org.xbib.graphics.svg.SVGUniverse;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.net.URI;
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class SVGIcon extends ImageIcon
|
||||
{
|
||||
public static final long serialVersionUID = 1;
|
||||
|
||||
public static final String PROP_AUTOSIZE = "PROP_AUTOSIZE";
|
||||
|
||||
private final PropertyChangeSupport changes = new PropertyChangeSupport(this);
|
||||
|
||||
SVGUniverse svgUniverse = SVGCache.getSVGUniverse();
|
||||
public static final int INTERP_NEAREST_NEIGHBOR = 0;
|
||||
public static final int INTERP_BILINEAR = 1;
|
||||
public static final int INTERP_BICUBIC = 2;
|
||||
|
||||
private boolean antiAlias;
|
||||
private int interpolation = INTERP_NEAREST_NEIGHBOR;
|
||||
private boolean clipToViewbox;
|
||||
|
||||
URI svgURI;
|
||||
|
||||
// private boolean scaleToFit;
|
||||
AffineTransform scaleXform = new AffineTransform();
|
||||
|
||||
public static final int AUTOSIZE_NONE = 0;
|
||||
public static final int AUTOSIZE_HORIZ = 1;
|
||||
public static final int AUTOSIZE_VERT = 2;
|
||||
public static final int AUTOSIZE_BESTFIT = 3;
|
||||
public static final int AUTOSIZE_STRETCH = 4;
|
||||
private int autosize = AUTOSIZE_NONE;
|
||||
|
||||
Dimension preferredSize;
|
||||
|
||||
/** Creates a new instance of SVGIcon */
|
||||
public SVGIcon()
|
||||
{
|
||||
}
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener p)
|
||||
{
|
||||
changes.addPropertyChangeListener(p);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener p)
|
||||
{
|
||||
changes.removePropertyChangeListener(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getImage()
|
||||
{
|
||||
BufferedImage bi = new BufferedImage(getIconWidth(), getIconHeight(), BufferedImage.TYPE_INT_ARGB);
|
||||
paintIcon(null, bi.getGraphics(), 0, 0);
|
||||
return bi;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return height of this icon
|
||||
*/
|
||||
public int getIconHeightIgnoreAutosize()
|
||||
{
|
||||
if (preferredSize != null &&
|
||||
(autosize == AUTOSIZE_VERT || autosize == AUTOSIZE_STRETCH
|
||||
|| autosize == AUTOSIZE_BESTFIT))
|
||||
{
|
||||
return preferredSize.height;
|
||||
}
|
||||
|
||||
SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
|
||||
if (diagram == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (int)diagram.getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return width of this icon
|
||||
*/
|
||||
|
||||
public int getIconWidthIgnoreAutosize()
|
||||
{
|
||||
if (preferredSize != null &&
|
||||
(autosize == AUTOSIZE_HORIZ || autosize == AUTOSIZE_STRETCH
|
||||
|| autosize == AUTOSIZE_BESTFIT))
|
||||
{
|
||||
return preferredSize.width;
|
||||
}
|
||||
|
||||
SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
|
||||
if (diagram == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (int)diagram.getWidth();
|
||||
}
|
||||
|
||||
private boolean isAutoSizeBestFitUseFixedHeight(final int iconWidthIgnoreAutosize, final int iconHeightIgnoreAutosize,
|
||||
final SVGDiagram diagram)
|
||||
{
|
||||
return iconHeightIgnoreAutosize/diagram.getHeight() < iconWidthIgnoreAutosize/diagram.getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconWidth()
|
||||
{
|
||||
final int iconWidthIgnoreAutosize = getIconWidthIgnoreAutosize();
|
||||
final int iconHeightIgnoreAutosize = getIconHeightIgnoreAutosize();
|
||||
final SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
|
||||
if (preferredSize != null && (autosize == AUTOSIZE_VERT ||
|
||||
(autosize == AUTOSIZE_BESTFIT && isAutoSizeBestFitUseFixedHeight(iconWidthIgnoreAutosize, iconHeightIgnoreAutosize, diagram))))
|
||||
{
|
||||
final double aspectRatio = diagram.getHeight()/diagram.getWidth();
|
||||
return (int)(iconHeightIgnoreAutosize / aspectRatio);
|
||||
}
|
||||
else
|
||||
{
|
||||
return iconWidthIgnoreAutosize;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconHeight()
|
||||
{
|
||||
final int iconWidthIgnoreAutosize = getIconWidthIgnoreAutosize();
|
||||
final int iconHeightIgnoreAutosize = getIconHeightIgnoreAutosize();
|
||||
final SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
|
||||
if (preferredSize != null && (autosize == AUTOSIZE_HORIZ ||
|
||||
(autosize == AUTOSIZE_BESTFIT && !isAutoSizeBestFitUseFixedHeight(iconWidthIgnoreAutosize, iconHeightIgnoreAutosize, diagram))))
|
||||
{
|
||||
final double aspectRatio = diagram.getHeight()/diagram.getWidth();
|
||||
return (int)(iconWidthIgnoreAutosize * aspectRatio);
|
||||
}
|
||||
else
|
||||
{
|
||||
return iconHeightIgnoreAutosize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draws the icon to the specified component.
|
||||
* @param comp - Component to draw icon to. This is ignored by SVGIcon, and can be set to null; only gg is used for drawing the icon
|
||||
* @param gg - Graphics context to render SVG content to
|
||||
* @param x - X coordinate to draw icon
|
||||
* @param y - Y coordinate to draw icon
|
||||
*/
|
||||
@Override
|
||||
public void paintIcon(Component comp, Graphics gg, int x, int y)
|
||||
{
|
||||
//Copy graphics object so that
|
||||
Graphics2D g = (Graphics2D)gg.create();
|
||||
paintIcon(comp, g, x, y);
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
private void paintIcon(Component comp, Graphics2D g, int x, int y)
|
||||
{
|
||||
Object oldAliasHint = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
|
||||
|
||||
Object oldInterpolationHint = g.getRenderingHint(RenderingHints.KEY_INTERPOLATION);
|
||||
switch (interpolation)
|
||||
{
|
||||
case INTERP_NEAREST_NEIGHBOR:
|
||||
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
|
||||
break;
|
||||
case INTERP_BILINEAR:
|
||||
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||
break;
|
||||
case INTERP_BICUBIC:
|
||||
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
|
||||
if (diagram == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g.translate(x, y);
|
||||
diagram.setIgnoringClipHeuristic(!clipToViewbox);
|
||||
if (clipToViewbox)
|
||||
{
|
||||
g.setClip(new Rectangle2D.Float(0, 0, diagram.getWidth(), diagram.getHeight()));
|
||||
}
|
||||
|
||||
|
||||
if (autosize == AUTOSIZE_NONE)
|
||||
{
|
||||
try
|
||||
{
|
||||
diagram.render(g);
|
||||
g.translate(-x, -y);
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAliasHint);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final int width = getIconWidthIgnoreAutosize();
|
||||
final int height = getIconHeightIgnoreAutosize();
|
||||
// int width = getWidth();
|
||||
// int height = getHeight();
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if (width == 0 || height == 0)
|
||||
// {
|
||||
// //Chances are we're rendering offscreen
|
||||
// Dimension dim = getSize();
|
||||
// width = dim.width;
|
||||
// height = dim.height;
|
||||
// return;
|
||||
// }
|
||||
|
||||
// g.setClip(0, 0, width, height);
|
||||
|
||||
|
||||
// final Rectangle2D.Double rect = new Rectangle2D.Double();
|
||||
// diagram.getViewRect(rect);
|
||||
//
|
||||
// scaleXform.setToScale(width / rect.width, height / rect.height);
|
||||
double diaWidth = diagram.getWidth();
|
||||
double diaHeight = diagram.getHeight();
|
||||
|
||||
double scaleW = 1;
|
||||
double scaleH = 1;
|
||||
if (autosize == AUTOSIZE_BESTFIT)
|
||||
{
|
||||
scaleW = scaleH = (height / diaHeight < width / diaWidth)
|
||||
? height / diaHeight : width / diaWidth;
|
||||
}
|
||||
else if (autosize == AUTOSIZE_HORIZ)
|
||||
{
|
||||
scaleW = scaleH = width / diaWidth;
|
||||
}
|
||||
else if (autosize == AUTOSIZE_VERT)
|
||||
{
|
||||
scaleW = scaleH = height / diaHeight;
|
||||
}
|
||||
else if (autosize == AUTOSIZE_STRETCH)
|
||||
{
|
||||
scaleW = width / diaWidth;
|
||||
scaleH = height / diaHeight;
|
||||
}
|
||||
scaleXform.setToScale(scaleW, scaleH);
|
||||
|
||||
AffineTransform oldXform = g.getTransform();
|
||||
g.transform(scaleXform);
|
||||
|
||||
try
|
||||
{
|
||||
diagram.render(g);
|
||||
}
|
||||
catch (SVGException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
g.setTransform(oldXform);
|
||||
|
||||
|
||||
g.translate(-x, -y);
|
||||
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAliasHint);
|
||||
if (oldInterpolationHint != null)
|
||||
{
|
||||
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, oldInterpolationHint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the universe this icon draws it's SVGDiagrams from
|
||||
*/
|
||||
public SVGUniverse getSvgUniverse()
|
||||
{
|
||||
return svgUniverse;
|
||||
}
|
||||
|
||||
public void setSvgUniverse(SVGUniverse svgUniverse)
|
||||
{
|
||||
SVGUniverse old = this.svgUniverse;
|
||||
this.svgUniverse = svgUniverse;
|
||||
changes.firePropertyChange("svgUniverse", old, svgUniverse);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the uni of the document being displayed by this icon
|
||||
*/
|
||||
public URI getSvgURI()
|
||||
{
|
||||
return svgURI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an SVG document from a URI.
|
||||
* @param svgURI - URI to load document from
|
||||
*/
|
||||
public void setSvgURI(URI svgURI)
|
||||
{
|
||||
URI old = this.svgURI;
|
||||
this.svgURI = svgURI;
|
||||
|
||||
SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
|
||||
if (diagram != null)
|
||||
{
|
||||
Dimension size = getPreferredSize();
|
||||
if (size == null)
|
||||
{
|
||||
size = new Dimension((int)diagram.getRoot().getDeviceWidth(), (int)diagram.getRoot().getDeviceHeight());
|
||||
}
|
||||
diagram.setDeviceViewport(new Rectangle(0, 0, size.width, size.height));
|
||||
}
|
||||
|
||||
changes.firePropertyChange("svgURI", old, svgURI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an SVG document from the classpath. This function is equivilant to
|
||||
* setSvgURI(new URI(getClass().getResource(resourcePath).toString());
|
||||
* @param resourcePath - resource to load
|
||||
*/
|
||||
public void setSvgResourcePath(String resourcePath)
|
||||
{
|
||||
URI old = this.svgURI;
|
||||
|
||||
try
|
||||
{
|
||||
svgURI = new URI(getClass().getResource(resourcePath).toString());
|
||||
changes.firePropertyChange("svgURI", old, svgURI);
|
||||
|
||||
SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
|
||||
if (diagram != null)
|
||||
{
|
||||
diagram.setDeviceViewport(new Rectangle(0, 0, preferredSize.width, preferredSize.height));
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
svgURI = old;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If this SVG document has a viewbox, if scaleToFit is set, will scale the viewbox to match the
|
||||
* preferred size of this icon
|
||||
* @deprecated
|
||||
* @return
|
||||
*/
|
||||
public boolean isScaleToFit()
|
||||
{
|
||||
return autosize == AUTOSIZE_STRETCH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public void setScaleToFit(boolean scaleToFit)
|
||||
{
|
||||
setAutosize(AUTOSIZE_STRETCH);
|
||||
// boolean old = this.scaleToFit;
|
||||
// this.scaleToFit = scaleToFit;
|
||||
// firePropertyChange("scaleToFit", old, scaleToFit);
|
||||
}
|
||||
|
||||
public Dimension getPreferredSize()
|
||||
{
|
||||
if (preferredSize == null)
|
||||
{
|
||||
SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
|
||||
if (diagram != null)
|
||||
{
|
||||
//preferredSize = new Dimension((int)diagram.getWidth(), (int)diagram.getHeight());
|
||||
setPreferredSize(new Dimension((int)diagram.getWidth(), (int)diagram.getHeight()));
|
||||
}
|
||||
}
|
||||
|
||||
return new Dimension(preferredSize);
|
||||
}
|
||||
|
||||
public void setPreferredSize(Dimension preferredSize)
|
||||
{
|
||||
Dimension old = this.preferredSize;
|
||||
this.preferredSize = preferredSize;
|
||||
|
||||
SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
|
||||
if (diagram != null)
|
||||
{
|
||||
diagram.setDeviceViewport(new Rectangle(0, 0, preferredSize.width, preferredSize.height));
|
||||
}
|
||||
|
||||
changes.firePropertyChange("preferredSize", old, preferredSize);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true if antiAliasing is turned on.
|
||||
* @deprecated
|
||||
*/
|
||||
public boolean getUseAntiAlias()
|
||||
{
|
||||
return getAntiAlias();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param antiAlias true to use antiAliasing.
|
||||
* @deprecated
|
||||
*/
|
||||
public void setUseAntiAlias(boolean antiAlias)
|
||||
{
|
||||
setAntiAlias(antiAlias);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if antiAliasing is turned on.
|
||||
*/
|
||||
public boolean getAntiAlias()
|
||||
{
|
||||
return antiAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param antiAlias true to use antiAliasing.
|
||||
*/
|
||||
public void setAntiAlias(boolean antiAlias)
|
||||
{
|
||||
boolean old = this.antiAlias;
|
||||
this.antiAlias = antiAlias;
|
||||
changes.firePropertyChange("antiAlias", old, antiAlias);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return interpolation used in rescaling images
|
||||
*/
|
||||
public int getInterpolation()
|
||||
{
|
||||
return interpolation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param interpolation Interpolation value used in rescaling images.
|
||||
* Should be one of
|
||||
* INTERP_NEAREST_NEIGHBOR - Fastest, one pixel resampling, poor quality
|
||||
* INTERP_BILINEAR - four pixel resampling
|
||||
* INTERP_BICUBIC - Slowest, nine pixel resampling, best quality
|
||||
*/
|
||||
public void setInterpolation(int interpolation)
|
||||
{
|
||||
int old = this.interpolation;
|
||||
this.interpolation = interpolation;
|
||||
changes.firePropertyChange("interpolation", old, interpolation);
|
||||
}
|
||||
|
||||
/**
|
||||
* clipToViewbox will set a clip box equivilant to the SVG's viewbox before
|
||||
* rendering.
|
||||
*/
|
||||
public boolean isClipToViewbox()
|
||||
{
|
||||
return clipToViewbox;
|
||||
}
|
||||
|
||||
public void setClipToViewbox(boolean clipToViewbox)
|
||||
{
|
||||
this.clipToViewbox = clipToViewbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the autosize
|
||||
*/
|
||||
public int getAutosize()
|
||||
{
|
||||
return autosize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param autosize the autosize to set
|
||||
*/
|
||||
public void setAutosize(int autosize)
|
||||
{
|
||||
int oldAutosize = this.autosize;
|
||||
this.autosize = autosize;
|
||||
changes.firePropertyChange(PROP_AUTOSIZE, oldAutosize, autosize);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||
</Form>
|
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
* 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 April 21, 2005, 10:43 AM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.app.beans;
|
||||
|
||||
import org.xbib.graphics.svg.SVGCache;
|
||||
import org.xbib.graphics.svg.SVGDiagram;
|
||||
import org.xbib.graphics.svg.SVGException;
|
||||
import org.xbib.graphics.svg.SVGUniverse;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.*;
|
||||
import java.net.*;
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class SVGPanel extends JPanel
|
||||
{
|
||||
public static final long serialVersionUID = 1;
|
||||
public static final String PROP_AUTOSIZE = "PROP_AUTOSIZE";
|
||||
|
||||
SVGUniverse svgUniverse = SVGCache.getSVGUniverse();
|
||||
|
||||
private boolean antiAlias;
|
||||
|
||||
// private String svgPath;
|
||||
URI svgURI;
|
||||
|
||||
// private boolean scaleToFit;
|
||||
AffineTransform scaleXform = new AffineTransform();
|
||||
|
||||
public static final int AUTOSIZE_NONE = 0;
|
||||
public static final int AUTOSIZE_HORIZ = 1;
|
||||
public static final int AUTOSIZE_VERT = 2;
|
||||
public static final int AUTOSIZE_BESTFIT = 3;
|
||||
public static final int AUTOSIZE_STRETCH = 4;
|
||||
private int autosize = AUTOSIZE_NONE;
|
||||
|
||||
/** Creates new form SVGIcon */
|
||||
public SVGPanel()
|
||||
{
|
||||
initComponents();
|
||||
}
|
||||
|
||||
public int getSVGHeight()
|
||||
{
|
||||
if (autosize == AUTOSIZE_VERT || autosize == AUTOSIZE_STRETCH
|
||||
|| autosize == AUTOSIZE_BESTFIT)
|
||||
{
|
||||
return getPreferredSize().height;
|
||||
}
|
||||
|
||||
SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
|
||||
if (diagram == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (int)diagram.getHeight();
|
||||
}
|
||||
|
||||
public int getSVGWidth()
|
||||
{
|
||||
if (autosize == AUTOSIZE_HORIZ || autosize == AUTOSIZE_STRETCH
|
||||
|| autosize == AUTOSIZE_BESTFIT)
|
||||
{
|
||||
return getPreferredSize().width;
|
||||
}
|
||||
|
||||
SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
|
||||
if (diagram == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (int)diagram.getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics gg)
|
||||
{
|
||||
super.paintComponent(gg);
|
||||
|
||||
Graphics2D g = (Graphics2D)gg.create();
|
||||
paintComponent(g);
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
private void paintComponent(Graphics2D g)
|
||||
{
|
||||
Object oldAliasHint = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
|
||||
|
||||
|
||||
SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
|
||||
if (diagram == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (autosize == AUTOSIZE_NONE)
|
||||
{
|
||||
try
|
||||
{
|
||||
diagram.render(this, g);
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAliasHint);
|
||||
}
|
||||
catch (SVGException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Dimension dim = getSize();
|
||||
final int width = dim.width;
|
||||
final int height = dim.height;
|
||||
|
||||
// final Rectangle2D.Double rect = new Rectangle2D.Double();
|
||||
// diagram.getViewRect(rect);
|
||||
|
||||
double diaWidth = diagram.getWidth();
|
||||
double diaHeight = diagram.getHeight();
|
||||
|
||||
double scaleW = 1;
|
||||
double scaleH = 1;
|
||||
if (autosize == AUTOSIZE_BESTFIT)
|
||||
{
|
||||
scaleW = scaleH = (height / diaHeight < width / diaWidth)
|
||||
? height / diaHeight : width / diaWidth;
|
||||
}
|
||||
else if (autosize == AUTOSIZE_HORIZ)
|
||||
{
|
||||
scaleW = scaleH = width / diaWidth;
|
||||
}
|
||||
else if (autosize == AUTOSIZE_VERT)
|
||||
{
|
||||
scaleW = scaleH = height / diaHeight;
|
||||
}
|
||||
else if (autosize == AUTOSIZE_STRETCH)
|
||||
{
|
||||
scaleW = width / diaWidth;
|
||||
scaleH = height / diaHeight;
|
||||
}
|
||||
scaleXform.setToScale(scaleW, scaleH);
|
||||
|
||||
AffineTransform oldXform = g.getTransform();
|
||||
g.transform(scaleXform);
|
||||
|
||||
try
|
||||
{
|
||||
diagram.render(g);
|
||||
}
|
||||
catch (SVGException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
g.setTransform(oldXform);
|
||||
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAliasHint);
|
||||
}
|
||||
|
||||
public SVGUniverse getSvgUniverse()
|
||||
{
|
||||
return svgUniverse;
|
||||
}
|
||||
|
||||
public void setSvgUniverse(SVGUniverse svgUniverse)
|
||||
{
|
||||
SVGUniverse old = this.svgUniverse;
|
||||
this.svgUniverse = svgUniverse;
|
||||
firePropertyChange("svgUniverse", old, svgUniverse);
|
||||
}
|
||||
|
||||
public URI getSvgURI()
|
||||
{
|
||||
return svgURI;
|
||||
}
|
||||
|
||||
public void setSvgURI(URI svgURI)
|
||||
{
|
||||
URI old = this.svgURI;
|
||||
this.svgURI = svgURI;
|
||||
firePropertyChange("svgURI", old, svgURI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Most resources your component will want to access will be resources on your classpath.
|
||||
* This method will interpret the passed string as a path in the classpath and use
|
||||
* Class.getResource() to determine the URI of the SVG.
|
||||
*/
|
||||
public void setSvgResourcePath(String resourcePath) throws SVGException
|
||||
{
|
||||
URI old = this.svgURI;
|
||||
|
||||
try
|
||||
{
|
||||
svgURI = new URI(getClass().getResource(resourcePath).toString());
|
||||
//System.err.println("SVGPanel: new URI " + svgURI + " from path " + resourcePath);
|
||||
|
||||
firePropertyChange("svgURI", old, svgURI);
|
||||
|
||||
repaint();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new SVGException("Could not resolve path " + resourcePath, e);
|
||||
// svgURI = old;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If this SVG document has a viewbox, if scaleToFit is set, will scale the viewbox to match the
|
||||
* preferred size of this icon
|
||||
* @deprecated
|
||||
* @return
|
||||
*/
|
||||
public boolean isScaleToFit()
|
||||
{
|
||||
return autosize == AUTOSIZE_STRETCH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public void setScaleToFit(boolean scaleToFit)
|
||||
{
|
||||
setAutosize(AUTOSIZE_STRETCH);
|
||||
// boolean old = this.scaleToFit;
|
||||
// this.scaleToFit = scaleToFit;
|
||||
// firePropertyChange("scaleToFit", old, scaleToFit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if antiAliasing is turned on.
|
||||
* @deprecated
|
||||
*/
|
||||
public boolean getUseAntiAlias()
|
||||
{
|
||||
return getAntiAlias();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param antiAlias true to use antiAliasing.
|
||||
* @deprecated
|
||||
*/
|
||||
public void setUseAntiAlias(boolean antiAlias)
|
||||
{
|
||||
setAntiAlias(antiAlias);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if antiAliasing is turned on.
|
||||
*/
|
||||
public boolean getAntiAlias()
|
||||
{
|
||||
return antiAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param antiAlias true to use antiAliasing.
|
||||
*/
|
||||
public void setAntiAlias(boolean antiAlias)
|
||||
{
|
||||
boolean old = this.antiAlias;
|
||||
this.antiAlias = antiAlias;
|
||||
firePropertyChange("antiAlias", old, antiAlias);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the autosize
|
||||
*/
|
||||
public int getAutosize()
|
||||
{
|
||||
return autosize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param autosize the autosize to set
|
||||
*/
|
||||
public void setAutosize(int autosize)
|
||||
{
|
||||
int oldAutosize = this.autosize;
|
||||
this.autosize = autosize;
|
||||
firePropertyChange(PROP_AUTOSIZE, oldAutosize, autosize);
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
|
||||
private void initComponents()
|
||||
{
|
||||
|
||||
setLayout(new java.awt.BorderLayout());
|
||||
|
||||
}
|
||||
// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.app.data;
|
||||
|
||||
import org.xbib.graphics.svg.SVGConst;
|
||||
import org.xbib.graphics.svg.util.Base64InputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class Handler extends URLStreamHandler
|
||||
{
|
||||
class Connection extends URLConnection
|
||||
{
|
||||
String mime;
|
||||
byte[] buf;
|
||||
|
||||
public Connection(URL url)
|
||||
{
|
||||
super(url);
|
||||
|
||||
String path = url.getPath();
|
||||
int idx = path.indexOf(';');
|
||||
mime = path.substring(0, idx);
|
||||
String content = path.substring(idx + 1);
|
||||
|
||||
if (content.startsWith("base64,"))
|
||||
{
|
||||
content = content.substring(7);
|
||||
try
|
||||
{
|
||||
//byte[] buf2 = new sun.misc.BASE64Decoder().decodeBuffer(content);
|
||||
//buf = new sun.misc.BASE64Decoder().decodeBuffer(content);
|
||||
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(content.getBytes());
|
||||
Base64InputStream b64is = new Base64InputStream(bis);
|
||||
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
byte[] tmp = new byte[2056];
|
||||
for (int size = b64is.read(tmp); size != -1; size = b64is.read(tmp))
|
||||
{
|
||||
bout.write(tmp, 0, size);
|
||||
}
|
||||
buf = bout.toByteArray();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeaderField(String name)
|
||||
{
|
||||
if ("content-type".equals(name))
|
||||
{
|
||||
return mime;
|
||||
}
|
||||
|
||||
return super.getHeaderField(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException
|
||||
{
|
||||
return new ByteArrayInputStream(buf);
|
||||
}
|
||||
|
||||
// public Object getContent() throws IOException
|
||||
// {
|
||||
// BufferedImage img = ImageIO.read(getInputStream());
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
protected URLConnection openConnection(URL u) throws IOException
|
||||
{
|
||||
return new Connection(u);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.app.data;
|
||||
|
||||
import java.net.URLStreamHandler;
|
||||
import java.net.URLStreamHandlerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class HandlerFactory implements URLStreamHandlerFactory
|
||||
{
|
||||
static Handler handler = new Handler();
|
||||
|
||||
public URLStreamHandler createURLStreamHandler(String protocol)
|
||||
{
|
||||
if ("data".equals(protocol))
|
||||
{
|
||||
return handler;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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 April 1, 2004, 6:40 AM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.composite;
|
||||
|
||||
import org.xbib.graphics.svg.SVGConst;
|
||||
import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class AdobeComposite implements Composite
|
||||
{
|
||||
public static final int CT_NORMAL = 0;
|
||||
public static final int CT_MULTIPLY = 1;
|
||||
public static final int CT_LAST = 2;
|
||||
|
||||
final int compositeType;
|
||||
final float extraAlpha;
|
||||
|
||||
/**
|
||||
* Creates a new instance of AdobeComposite
|
||||
* @param compositeType
|
||||
* @param extraAlpha
|
||||
*/
|
||||
public AdobeComposite(int compositeType, float extraAlpha)
|
||||
{
|
||||
this.compositeType = compositeType;
|
||||
this.extraAlpha = extraAlpha;
|
||||
|
||||
if (compositeType < 0 || compositeType >= CT_LAST)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, "Invalid composite type");
|
||||
}
|
||||
|
||||
if (extraAlpha < 0f || extraAlpha > 1f)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, "Invalid alpha");
|
||||
}
|
||||
}
|
||||
|
||||
public int getCompositeType() { return compositeType; }
|
||||
|
||||
public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints)
|
||||
{
|
||||
return new AdobeCompositeContext(compositeType, extraAlpha);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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 April 1, 2004, 6:41 AM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.composite;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class AdobeCompositeContext implements CompositeContext
|
||||
{
|
||||
final int compositeType;
|
||||
final float extraAlpha;
|
||||
|
||||
float[] rgba_src = new float[4];
|
||||
float[] rgba_dstIn = new float[4];
|
||||
float[] rgba_dstOut = new float[4];
|
||||
|
||||
/** Creates a new instance of AdobeCompositeContext
|
||||
* @param compositeType
|
||||
* @param extraAlpha
|
||||
*/
|
||||
public AdobeCompositeContext(int compositeType, float extraAlpha)
|
||||
{
|
||||
this.compositeType = compositeType;
|
||||
this.extraAlpha = extraAlpha;
|
||||
|
||||
rgba_dstOut[3] = 1f;
|
||||
}
|
||||
|
||||
public void compose(Raster src, Raster dstIn, WritableRaster dstOut)
|
||||
{
|
||||
int width = src.getWidth();
|
||||
int height = src.getHeight();
|
||||
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
for (int i = 0; i < width; i++)
|
||||
{
|
||||
src.getPixel(i, j, rgba_src);
|
||||
dstIn.getPixel(i, j, rgba_dstIn);
|
||||
|
||||
//Ignore transparent pixels
|
||||
if (rgba_src[3] == 0)
|
||||
{
|
||||
// dstOut.setPixel(i, j, rgba_dstIn);
|
||||
continue;
|
||||
}
|
||||
|
||||
float alpha = rgba_src[3];
|
||||
|
||||
switch (compositeType)
|
||||
{
|
||||
default:
|
||||
case AdobeComposite.CT_NORMAL:
|
||||
rgba_dstOut[0] = rgba_src[0] * alpha + rgba_dstIn[0] * (1f - alpha);
|
||||
rgba_dstOut[1] = rgba_src[1] * alpha + rgba_dstIn[1] * (1f - alpha);
|
||||
rgba_dstOut[2] = rgba_src[2] * alpha + rgba_dstIn[2] * (1f - alpha);
|
||||
break;
|
||||
case AdobeComposite.CT_MULTIPLY:
|
||||
rgba_dstOut[0] = rgba_src[0] * rgba_dstIn[0] * alpha + rgba_dstIn[0] * (1f - alpha);
|
||||
rgba_dstOut[1] = rgba_src[1] * rgba_dstIn[1] * alpha + rgba_dstIn[1] * (1f - alpha);
|
||||
rgba_dstOut[2] = rgba_src[2] * rgba_dstIn[2] * alpha + rgba_dstIn[2] * (1f - alpha);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 8:40 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.pathcmd;
|
||||
|
||||
//import org.apache.batik.ext.awt.geom.ExtendedGeneralPath;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.*;
|
||||
|
||||
/**
|
||||
* This is a little used SVG function, as most editors will save curves as
|
||||
* Beziers. To reduce the need to rely on the Batik library, this functionallity
|
||||
* is being bypassed for the time being. In the future, it would be nice to
|
||||
* extend the GeneralPath command to include the arcTo ability provided by Batik.
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Arc extends PathCommand
|
||||
{
|
||||
|
||||
public float rx = 0f;
|
||||
public float ry = 0f;
|
||||
public float xAxisRot = 0f;
|
||||
public boolean largeArc = false;
|
||||
public boolean sweep = false;
|
||||
public float x = 0f;
|
||||
public float y = 0f;
|
||||
|
||||
/** Creates a new instance of MoveTo */
|
||||
public Arc() {
|
||||
}
|
||||
|
||||
public Arc(boolean isRelative, float rx, float ry, float xAxisRot, boolean largeArc, boolean sweep, float x, float y) {
|
||||
super(isRelative);
|
||||
this.rx = rx;
|
||||
this.ry = ry;
|
||||
this.xAxisRot = xAxisRot;
|
||||
this.largeArc = largeArc;
|
||||
this.sweep = sweep;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
// public void appendPath(ExtendedGeneralPath path, BuildHistory hist)
|
||||
@Override
|
||||
public void appendPath(GeneralPath path, BuildHistory hist)
|
||||
{
|
||||
float offx = isRelative ? hist.lastPoint.x : 0f;
|
||||
float offy = isRelative ? hist.lastPoint.y : 0f;
|
||||
|
||||
arcTo(path, rx, ry, xAxisRot, largeArc, sweep,
|
||||
x + offx, y + offy,
|
||||
hist.lastPoint.x, hist.lastPoint.y);
|
||||
// path.lineTo(x + offx, y + offy);
|
||||
// hist.setPoint(x + offx, y + offy);
|
||||
hist.setLastPoint(x + offx, y + offy);
|
||||
hist.setLastKnot(x + offx, y + offy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumKnotsAdded()
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an elliptical arc, defined by two radii, an angle from the
|
||||
* x-axis, a flag to choose the large arc or not, a flag to
|
||||
* indicate if we increase or decrease the angles and the final
|
||||
* point of the arc.
|
||||
*
|
||||
* @param path The path that the arc will be appended to.
|
||||
*
|
||||
* @param rx the x radius of the ellipse
|
||||
* @param ry the y radius of the ellipse
|
||||
*
|
||||
* @param angle the angle from the x-axis of the current
|
||||
* coordinate system to the x-axis of the ellipse in degrees.
|
||||
*
|
||||
* @param largeArcFlag the large arc flag. If true the arc
|
||||
* spanning less than or equal to 180 degrees is chosen, otherwise
|
||||
* the arc spanning greater than 180 degrees is chosen
|
||||
*
|
||||
* @param sweepFlag the sweep flag. If true the line joining
|
||||
* center to arc sweeps through decreasing angles otherwise it
|
||||
* sweeps through increasing angles
|
||||
*
|
||||
* @param x the absolute x coordinate of the final point of the arc.
|
||||
* @param y the absolute y coordinate of the final point of the arc.
|
||||
* @param x0 - The absolute x coordinate of the initial point of the arc.
|
||||
* @param y0 - The absolute y coordinate of the initial point of the arc.
|
||||
*/
|
||||
public void arcTo(GeneralPath path, float rx, float ry,
|
||||
float angle,
|
||||
boolean largeArcFlag,
|
||||
boolean sweepFlag,
|
||||
float x, float y, float x0, float y0)
|
||||
{
|
||||
|
||||
// Ensure radii are valid
|
||||
if (rx == 0 || ry == 0) {
|
||||
path.lineTo((float) x, (float) y);
|
||||
return;
|
||||
}
|
||||
|
||||
if (x0 == x && y0 == y) {
|
||||
// If the endpoints (x, y) and (x0, y0) are identical, then this
|
||||
// is equivalent to omitting the elliptical arc segment entirely.
|
||||
return;
|
||||
}
|
||||
|
||||
Arc2D arc = computeArc(x0, y0, rx, ry, angle,
|
||||
largeArcFlag, sweepFlag, x, y);
|
||||
if (arc == null) return;
|
||||
|
||||
AffineTransform t = AffineTransform.getRotateInstance
|
||||
(Math.toRadians(angle), arc.getCenterX(), arc.getCenterY());
|
||||
Shape s = t.createTransformedShape(arc);
|
||||
path.append(s, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This constructs an unrotated Arc2D from the SVG specification of an
|
||||
* Elliptical arc. To get the final arc you need to apply a rotation
|
||||
* transform such as:
|
||||
*
|
||||
* AffineTransform.getRotateInstance
|
||||
* (angle, arc.getX()+arc.getWidth()/2, arc.getY()+arc.getHeight()/2);
|
||||
*
|
||||
* @param x0 origin of arc in x
|
||||
* @param y0 origin of arc in y
|
||||
* @param rx radius of arc in x
|
||||
* @param ry radius of arc in y
|
||||
* @param angle number of radians in arc
|
||||
* @param largeArcFlag
|
||||
* @param sweepFlag
|
||||
* @param x ending coordinate of arc in x
|
||||
* @param y ending coordinate of arc in y
|
||||
* @return arc shape
|
||||
*
|
||||
*/
|
||||
public static Arc2D computeArc(double x0, double y0,
|
||||
double rx, double ry,
|
||||
double angle,
|
||||
boolean largeArcFlag,
|
||||
boolean sweepFlag,
|
||||
double x, double y) {
|
||||
//
|
||||
// Elliptical arc implementation based on the SVG specification notes
|
||||
//
|
||||
|
||||
// Compute the half distance between the current and the final point
|
||||
double dx2 = (x0 - x) / 2.0;
|
||||
double dy2 = (y0 - y) / 2.0;
|
||||
// Convert angle from degrees to radians
|
||||
angle = Math.toRadians(angle % 360.0);
|
||||
double cosAngle = Math.cos(angle);
|
||||
double sinAngle = Math.sin(angle);
|
||||
|
||||
//
|
||||
// Step 1 : Compute (x1, y1)
|
||||
//
|
||||
double x1 = (cosAngle * dx2 + sinAngle * dy2);
|
||||
double y1 = (-sinAngle * dx2 + cosAngle * dy2);
|
||||
// Ensure radii are large enough
|
||||
rx = Math.abs(rx);
|
||||
ry = Math.abs(ry);
|
||||
double Prx = rx * rx;
|
||||
double Pry = ry * ry;
|
||||
double Px1 = x1 * x1;
|
||||
double Py1 = y1 * y1;
|
||||
// check that radii are large enough
|
||||
double radiiCheck = Px1/Prx + Py1/Pry;
|
||||
if (radiiCheck > 1) {
|
||||
rx = Math.sqrt(radiiCheck) * rx;
|
||||
ry = Math.sqrt(radiiCheck) * ry;
|
||||
Prx = rx * rx;
|
||||
Pry = ry * ry;
|
||||
}
|
||||
|
||||
//
|
||||
// Step 2 : Compute (cx1, cy1)
|
||||
//
|
||||
double sign = (largeArcFlag == sweepFlag) ? -1 : 1;
|
||||
double sq = ((Prx*Pry)-(Prx*Py1)-(Pry*Px1)) / ((Prx*Py1)+(Pry*Px1));
|
||||
sq = (sq < 0) ? 0 : sq;
|
||||
double coef = (sign * Math.sqrt(sq));
|
||||
double cx1 = coef * ((rx * y1) / ry);
|
||||
double cy1 = coef * -((ry * x1) / rx);
|
||||
|
||||
//
|
||||
// Step 3 : Compute (cx, cy) from (cx1, cy1)
|
||||
//
|
||||
double sx2 = (x0 + x) / 2.0;
|
||||
double sy2 = (y0 + y) / 2.0;
|
||||
double cx = sx2 + (cosAngle * cx1 - sinAngle * cy1);
|
||||
double cy = sy2 + (sinAngle * cx1 + cosAngle * cy1);
|
||||
|
||||
//
|
||||
// Step 4 : Compute the angleStart (angle1) and the angleExtent (dangle)
|
||||
//
|
||||
double ux = (x1 - cx1) / rx;
|
||||
double uy = (y1 - cy1) / ry;
|
||||
double vx = (-x1 - cx1) / rx;
|
||||
double vy = (-y1 - cy1) / ry;
|
||||
double p, n;
|
||||
// Compute the angle start
|
||||
n = Math.sqrt((ux * ux) + (uy * uy));
|
||||
p = ux; // (1 * ux) + (0 * uy)
|
||||
sign = (uy < 0) ? -1d : 1d;
|
||||
double angleStart = Math.toDegrees(sign * Math.acos(p / n));
|
||||
|
||||
// Compute the angle extent
|
||||
n = Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy));
|
||||
p = ux * vx + uy * vy;
|
||||
sign = (ux * vy - uy * vx < 0) ? -1d : 1d;
|
||||
double angleExtent = Math.toDegrees(sign * Math.acos(p / n));
|
||||
if(!sweepFlag && angleExtent > 0) {
|
||||
angleExtent -= 360f;
|
||||
} else if (sweepFlag && angleExtent < 0) {
|
||||
angleExtent += 360f;
|
||||
}
|
||||
angleExtent %= 360f;
|
||||
angleStart %= 360f;
|
||||
|
||||
//
|
||||
// We can now build the resulting Arc2D in double precision
|
||||
//
|
||||
Arc2D.Double arc = new Arc2D.Double();
|
||||
arc.x = cx - rx;
|
||||
arc.y = cy - ry;
|
||||
arc.width = rx * 2.0;
|
||||
arc.height = ry * 2.0;
|
||||
arc.start = -angleStart;
|
||||
arc.extent = -angleExtent;
|
||||
|
||||
return arc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "A " + rx + " " + ry
|
||||
+ " " + xAxisRot + " " + largeArc
|
||||
+ " " + sweep
|
||||
+ " " + x + " " + y;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 9:18 PM
|
||||
*/
|
||||
package org.xbib.graphics.svg.pathcmd;
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
/**
|
||||
* When building a path from command segments, most need to cache information
|
||||
* (such as the point finished at) for future commands. This structure allows
|
||||
* that
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class BuildHistory
|
||||
{
|
||||
|
||||
// Point2D.Float[] history = new Point2D.Float[2];
|
||||
// Point2D.Float[] history = {new Point2D.Float(), new Point2D.Float()};
|
||||
// Point2D.Float start = new Point2D.Float();
|
||||
Point2D.Float startPoint = new Point2D.Float();
|
||||
Point2D.Float lastPoint = new Point2D.Float();
|
||||
Point2D.Float lastKnot = new Point2D.Float();
|
||||
boolean init;
|
||||
//int length = 0;
|
||||
|
||||
/**
|
||||
* Creates a new instance of BuildHistory
|
||||
*/
|
||||
public BuildHistory()
|
||||
{
|
||||
}
|
||||
|
||||
public void setStartPoint(float x, float y)
|
||||
{
|
||||
startPoint.setLocation(x, y);
|
||||
}
|
||||
|
||||
public void setLastPoint(float x, float y)
|
||||
{
|
||||
lastPoint.setLocation(x, y);
|
||||
}
|
||||
|
||||
public void setLastKnot(float x, float y)
|
||||
{
|
||||
lastKnot.setLocation(x, y);
|
||||
}
|
||||
// public void setPoint(float x, float y)
|
||||
// {
|
||||
// history[0].setLocation(x, y);
|
||||
// length = 1;
|
||||
// }
|
||||
// public void setStart(float x, float y)
|
||||
// {
|
||||
// start.setLocation(x, y);
|
||||
// }
|
||||
// public void setPointAndKnot(float x, float y, float kx, float ky)
|
||||
// {
|
||||
// history[0].setLocation(x, y);
|
||||
// history[1].setLocation(kx, ky);
|
||||
// length = 2;
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 8:40 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.pathcmd;
|
||||
|
||||
//import org.apache.batik.ext.awt.geom.ExtendedGeneralPath;
|
||||
import java.awt.geom.*;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Cubic extends PathCommand {
|
||||
|
||||
public float k1x = 0f;
|
||||
public float k1y = 0f;
|
||||
public float k2x = 0f;
|
||||
public float k2y = 0f;
|
||||
public float x = 0f;
|
||||
public float y = 0f;
|
||||
|
||||
/** Creates a new instance of MoveTo */
|
||||
public Cubic() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "C " + k1x + " " + k1y
|
||||
+ " " + k2x + " " + k2y
|
||||
+ " " + x + " " + y;
|
||||
}
|
||||
|
||||
public Cubic(boolean isRelative, float k1x, float k1y, float k2x, float k2y, float x, float y) {
|
||||
super(isRelative);
|
||||
this.k1x = k1x;
|
||||
this.k1y = k1y;
|
||||
this.k2x = k2x;
|
||||
this.k2y = k2y;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
// public void appendPath(ExtendedGeneralPath path, BuildHistory hist)
|
||||
@Override
|
||||
public void appendPath(GeneralPath path, BuildHistory hist)
|
||||
{
|
||||
float offx = isRelative ? hist.lastPoint.x : 0f;
|
||||
float offy = isRelative ? hist.lastPoint.y : 0f;
|
||||
|
||||
path.curveTo(k1x + offx, k1y + offy,
|
||||
k2x + offx, k2y + offy,
|
||||
x + offx, y + offy);
|
||||
// hist.setPointAndKnot(x + offx, y + offy, k2x + offx, k2y + offy);
|
||||
hist.setLastPoint(x + offx, y + offy);
|
||||
hist.setLastKnot(k2x + offx, k2y + offy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumKnotsAdded()
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 8:40 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.pathcmd;
|
||||
|
||||
//import org.apache.batik.ext.awt.geom.ExtendedGeneralPath;
|
||||
import java.awt.geom.*;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class CubicSmooth extends PathCommand {
|
||||
|
||||
public float x = 0f;
|
||||
public float y = 0f;
|
||||
public float k2x = 0f;
|
||||
public float k2y = 0f;
|
||||
|
||||
/** Creates a new instance of MoveTo */
|
||||
public CubicSmooth() {
|
||||
}
|
||||
|
||||
public CubicSmooth(boolean isRelative, float k2x, float k2y, float x, float y) {
|
||||
super(isRelative);
|
||||
this.k2x = k2x;
|
||||
this.k2y = k2y;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
// public void appendPath(ExtendedGeneralPath path, BuildHistory hist)
|
||||
@Override
|
||||
public void appendPath(GeneralPath path, BuildHistory hist)
|
||||
{
|
||||
float offx = isRelative ? hist.lastPoint.x : 0f;
|
||||
float offy = isRelative ? hist.lastPoint.y : 0f;
|
||||
|
||||
float oldKx = hist.lastKnot.x;
|
||||
float oldKy = hist.lastKnot.y;
|
||||
float oldX = hist.lastPoint.x;
|
||||
float oldY = hist.lastPoint.y;
|
||||
//Calc knot as reflection of old knot
|
||||
float k1x = oldX * 2f - oldKx;
|
||||
float k1y = oldY * 2f - oldKy;
|
||||
|
||||
path.curveTo(k1x, k1y, k2x + offx, k2y + offy, x + offx, y + offy);
|
||||
hist.setLastPoint(x + offx, y + offy);
|
||||
hist.setLastKnot(k2x + offx, k2y + offy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumKnotsAdded()
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "S " + k2x + " " + k2y
|
||||
+ " " + x + " " + y;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 8:40 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.pathcmd;
|
||||
|
||||
//import org.apache.batik.ext.awt.geom.ExtendedGeneralPath;
|
||||
import java.awt.geom.*;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Horizontal extends PathCommand {
|
||||
|
||||
public float x = 0f;
|
||||
|
||||
/** Creates a new instance of MoveTo */
|
||||
public Horizontal() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "H " + x;
|
||||
}
|
||||
|
||||
public Horizontal(boolean isRelative, float x) {
|
||||
super(isRelative);
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
|
||||
// public void appendPath(ExtendedGeneralPath path, BuildHistory hist)
|
||||
@Override
|
||||
public void appendPath(GeneralPath path, BuildHistory hist)
|
||||
{
|
||||
float offx = isRelative ? hist.lastPoint.x : 0f;
|
||||
float offy = hist.lastPoint.y;
|
||||
|
||||
path.lineTo(x + offx, offy);
|
||||
hist.setLastPoint(x + offx, offy);
|
||||
hist.setLastKnot(x + offx, offy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumKnotsAdded()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 8:40 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.pathcmd;
|
||||
|
||||
//import org.apache.batik.ext.awt.geom.ExtendedGeneralPath;
|
||||
import java.awt.geom.*;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class LineTo extends PathCommand {
|
||||
|
||||
public float x = 0f;
|
||||
public float y = 0f;
|
||||
|
||||
/** Creates a new instance of MoveTo */
|
||||
public LineTo() {
|
||||
}
|
||||
|
||||
public LineTo(boolean isRelative, float x, float y) {
|
||||
super(isRelative);
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
|
||||
// public void appendPath(ExtendedGeneralPath path, BuildHistory hist)
|
||||
@Override
|
||||
public void appendPath(GeneralPath path, BuildHistory hist)
|
||||
{
|
||||
float offx = isRelative ? hist.lastPoint.x : 0f;
|
||||
float offy = isRelative ? hist.lastPoint.y : 0f;
|
||||
|
||||
path.lineTo(x + offx, y + offy);
|
||||
hist.setLastPoint(x + offx, y + offy);
|
||||
hist.setLastKnot(x + offx, y + offy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumKnotsAdded()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "L " + x + " " + y;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 8:40 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.pathcmd;
|
||||
|
||||
//import org.apache.batik.ext.awt.geom.ExtendedGeneralPath;
|
||||
import java.awt.geom.*;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class MoveTo extends PathCommand {
|
||||
|
||||
public float x = 0f;
|
||||
public float y = 0f;
|
||||
|
||||
/** Creates a new instance of MoveTo */
|
||||
public MoveTo() {
|
||||
}
|
||||
|
||||
public MoveTo(boolean isRelative, float x, float y) {
|
||||
super(isRelative);
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
// public void appendPath(ExtendedGeneralPath path, BuildHistory hist)
|
||||
@Override
|
||||
public void appendPath(GeneralPath path, BuildHistory hist)
|
||||
{
|
||||
float offx = isRelative ? hist.lastPoint.x : 0f;
|
||||
float offy = isRelative ? hist.lastPoint.y : 0f;
|
||||
|
||||
path.moveTo(x + offx, y + offy);
|
||||
hist.setStartPoint(x + offx, y + offy);
|
||||
hist.setLastPoint(x + offx, y + offy);
|
||||
hist.setLastKnot(x + offx, y + offy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumKnotsAdded()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "M " + x + " " + y;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 8:39 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.pathcmd;
|
||||
|
||||
//import org.apache.batik.ext.awt.geom.ExtendedGeneralPath;
|
||||
import java.awt.geom.*;
|
||||
|
||||
/**
|
||||
* This is the element of a path and contains instructions for rendering a
|
||||
* portion of the path
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
abstract public class PathCommand {
|
||||
|
||||
public boolean isRelative = false;
|
||||
|
||||
/** Creates a new instance of PathCommand */
|
||||
public PathCommand() {
|
||||
}
|
||||
|
||||
public PathCommand(boolean isRelative) {
|
||||
this.isRelative = isRelative;
|
||||
}
|
||||
|
||||
// abstract public void appendPath(ExtendedGeneralPath path, BuildHistory hist);
|
||||
abstract public void appendPath(GeneralPath path, BuildHistory hist);
|
||||
|
||||
abstract public int getNumKnotsAdded();
|
||||
}
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
package org.xbib.graphics.svg.pathcmd;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A helper for parsing {@link PathCommand}s.
|
||||
*
|
||||
* @author Jannis Weis
|
||||
*/
|
||||
public class PathParser
|
||||
{
|
||||
private final String input;
|
||||
private final int inputLength;
|
||||
private int index;
|
||||
private char currentCommand;
|
||||
|
||||
public PathParser(String input) {
|
||||
this.input = input.trim();
|
||||
this.inputLength = this.input.length();
|
||||
}
|
||||
|
||||
private boolean isCommandChar(char c)
|
||||
{
|
||||
return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';
|
||||
}
|
||||
|
||||
private boolean isWhiteSpaceOrSeparator(char c)
|
||||
{
|
||||
return c <= ' ' || c == ',';
|
||||
}
|
||||
|
||||
private char peek()
|
||||
{
|
||||
return input.charAt(index);
|
||||
}
|
||||
|
||||
private void consume()
|
||||
{
|
||||
index++;
|
||||
}
|
||||
|
||||
private boolean hasNext()
|
||||
{
|
||||
return index < inputLength;
|
||||
}
|
||||
|
||||
// This only checks for the rough structure of a number as we need to know
|
||||
// when to separate the next token.
|
||||
// Explicit parsing is done by Float#parseFloat.
|
||||
private boolean isValidNumberChar(char c, NumberCharState state)
|
||||
{
|
||||
boolean valid = '0' <= c && c <= '9';
|
||||
if (valid && state.iteration == 1 && input.charAt(index - 1) == '0')
|
||||
{
|
||||
// Break up combined zeros into multiple numbers.
|
||||
return false;
|
||||
}
|
||||
state.signAllowed = state.signAllowed && !valid;
|
||||
if (state.dotAllowed && !valid)
|
||||
{
|
||||
valid = c == '.';
|
||||
state.dotAllowed = !valid;
|
||||
}
|
||||
if (state.signAllowed && !valid)
|
||||
{
|
||||
valid = c == '+' || c == '-';
|
||||
state.signAllowed = valid;
|
||||
}
|
||||
if (state.exponentAllowed && !valid)
|
||||
{
|
||||
// Possible exponent notation. Needs at least one preceding number
|
||||
valid = c == 'e' || c == 'E';
|
||||
state.exponentAllowed = !valid;
|
||||
state.signAllowed = valid;
|
||||
}
|
||||
state.iteration++;
|
||||
return valid;
|
||||
}
|
||||
|
||||
private void consumeWhiteSpaceOrSeparator() {
|
||||
while (hasNext() && isWhiteSpaceOrSeparator(peek())) {
|
||||
consume();
|
||||
}
|
||||
}
|
||||
|
||||
private float nextFloat()
|
||||
{
|
||||
int start = index;
|
||||
NumberCharState state = new NumberCharState();
|
||||
while (hasNext() && isValidNumberChar(peek(), state)) {
|
||||
consume();
|
||||
}
|
||||
int end = index;
|
||||
consumeWhiteSpaceOrSeparator();
|
||||
String token = input.substring(start, end);
|
||||
try
|
||||
{
|
||||
return Float.parseFloat(token);
|
||||
} catch (NumberFormatException e)
|
||||
{
|
||||
String msg = "Unexpected element while parsing cmd '" + currentCommand
|
||||
+ "' encountered token '" + token + "' rest=" + input.substring(start, Math.min(input.length(), start + 10))
|
||||
+ " (index=" + index + " in input=" + input + ")";
|
||||
throw new IllegalStateException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
public PathCommand[] parsePathCommand()
|
||||
{
|
||||
List<PathCommand> commands = new ArrayList<>();
|
||||
|
||||
currentCommand = 'Z';
|
||||
while (hasNext())
|
||||
{
|
||||
char peekChar = peek();
|
||||
if (isCommandChar(peekChar))
|
||||
{
|
||||
consume();
|
||||
currentCommand = peekChar;
|
||||
}
|
||||
consumeWhiteSpaceOrSeparator();
|
||||
|
||||
PathCommand cmd;
|
||||
switch (currentCommand)
|
||||
{
|
||||
case 'M':
|
||||
cmd = new MoveTo(false, nextFloat(), nextFloat());
|
||||
currentCommand = 'L';
|
||||
break;
|
||||
case 'm':
|
||||
cmd = new MoveTo(true, nextFloat(), nextFloat());
|
||||
currentCommand = 'l';
|
||||
break;
|
||||
case 'L':
|
||||
cmd = new LineTo(false, nextFloat(), nextFloat());
|
||||
break;
|
||||
case 'l':
|
||||
cmd = new LineTo(true, nextFloat(), nextFloat());
|
||||
break;
|
||||
case 'H':
|
||||
cmd = new Horizontal(false, nextFloat());
|
||||
break;
|
||||
case 'h':
|
||||
cmd = new Horizontal(true, nextFloat());
|
||||
break;
|
||||
case 'V':
|
||||
cmd = new Vertical(false, nextFloat());
|
||||
break;
|
||||
case 'v':
|
||||
cmd = new Vertical(true, nextFloat());
|
||||
break;
|
||||
case 'A':
|
||||
cmd = new Arc(false, nextFloat(), nextFloat(),
|
||||
nextFloat(),
|
||||
nextFloat() == 1f, nextFloat() == 1f,
|
||||
nextFloat(), nextFloat());
|
||||
break;
|
||||
case 'a':
|
||||
cmd = new Arc(true, nextFloat(), nextFloat(),
|
||||
nextFloat(),
|
||||
nextFloat() == 1f, nextFloat() == 1f,
|
||||
nextFloat(), nextFloat());
|
||||
break;
|
||||
case 'Q':
|
||||
cmd = new Quadratic(false, nextFloat(), nextFloat(),
|
||||
nextFloat(), nextFloat());
|
||||
break;
|
||||
case 'q':
|
||||
cmd = new Quadratic(true, nextFloat(), nextFloat(),
|
||||
nextFloat(), nextFloat());
|
||||
break;
|
||||
case 'T':
|
||||
cmd = new QuadraticSmooth(false, nextFloat(), nextFloat());
|
||||
break;
|
||||
case 't':
|
||||
cmd = new QuadraticSmooth(true, nextFloat(), nextFloat());
|
||||
break;
|
||||
case 'C':
|
||||
cmd = new Cubic(false, nextFloat(), nextFloat(),
|
||||
nextFloat(), nextFloat(),
|
||||
nextFloat(), nextFloat());
|
||||
break;
|
||||
case 'c':
|
||||
cmd = new Cubic(true, nextFloat(), nextFloat(),
|
||||
nextFloat(), nextFloat(),
|
||||
nextFloat(), nextFloat());
|
||||
break;
|
||||
case 'S':
|
||||
cmd = new CubicSmooth(false, nextFloat(), nextFloat(),
|
||||
nextFloat(), nextFloat());
|
||||
break;
|
||||
case 's':
|
||||
cmd = new CubicSmooth(true, nextFloat(), nextFloat(),
|
||||
nextFloat(), nextFloat());
|
||||
break;
|
||||
case 'Z':
|
||||
case 'z':
|
||||
cmd = new Terminal();
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Invalid path element "
|
||||
+ currentCommand + "(at index=" + index + " in input=" + input + ")");
|
||||
}
|
||||
commands.add(cmd);
|
||||
}
|
||||
return commands.toArray(new PathCommand[0]);
|
||||
}
|
||||
|
||||
private static class NumberCharState
|
||||
{
|
||||
int iteration = 0;
|
||||
boolean dotAllowed = true;
|
||||
boolean signAllowed = true;
|
||||
boolean exponentAllowed = true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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 10, 2005, 5:56 AM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.pathcmd;
|
||||
|
||||
import java.awt.geom.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class PathUtil
|
||||
{
|
||||
|
||||
/** Creates a new instance of PathUtil */
|
||||
public PathUtil()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a GeneralPath into an SVG representation
|
||||
*
|
||||
* @param path The shape to be encoded
|
||||
* @return A string encoding the path using the SVG path notation
|
||||
*/
|
||||
public static String buildPathString(GeneralPath path)
|
||||
{
|
||||
float[] coords = new float[6];
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
for (PathIterator pathIt = path.getPathIterator(new AffineTransform()); !pathIt.isDone(); pathIt.next())
|
||||
{
|
||||
int segId = pathIt.currentSegment(coords);
|
||||
|
||||
switch (segId)
|
||||
{
|
||||
case PathIterator.SEG_CLOSE:
|
||||
{
|
||||
sb.append(" Z");
|
||||
break;
|
||||
}
|
||||
case PathIterator.SEG_CUBICTO:
|
||||
{
|
||||
sb.append(" C " + coords[0] + " " + coords[1] + " " + coords[2] + " " + coords[3] + " " + coords[4] + " " + coords[5]);
|
||||
break;
|
||||
}
|
||||
case PathIterator.SEG_LINETO:
|
||||
{
|
||||
sb.append(" L " + coords[0] + " " + coords[1]);
|
||||
break;
|
||||
}
|
||||
case PathIterator.SEG_MOVETO:
|
||||
{
|
||||
sb.append(" M " + coords[0] + " " + coords[1]);
|
||||
break;
|
||||
}
|
||||
case PathIterator.SEG_QUADTO:
|
||||
{
|
||||
sb.append(" Q " + coords[0] + " " + coords[1] + " " + coords[2] + " " + coords[3]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 8:40 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.pathcmd;
|
||||
|
||||
//import org.apache.batik.ext.awt.geom.ExtendedGeneralPath;
|
||||
import java.awt.geom.*;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Quadratic extends PathCommand {
|
||||
|
||||
public float kx = 0f;
|
||||
public float ky = 0f;
|
||||
public float x = 0f;
|
||||
public float y = 0f;
|
||||
|
||||
/** Creates a new instance of MoveTo */
|
||||
public Quadratic() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Q " + kx + " " + ky
|
||||
+ " " + x + " " + y;
|
||||
}
|
||||
|
||||
public Quadratic(boolean isRelative, float kx, float ky, float x, float y) {
|
||||
super(isRelative);
|
||||
this.kx = kx;
|
||||
this.ky = ky;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
// public void appendPath(ExtendedGeneralPath path, BuildHistory hist)
|
||||
@Override
|
||||
public void appendPath(GeneralPath path, BuildHistory hist)
|
||||
{
|
||||
float offx = isRelative ? hist.lastPoint.x : 0f;
|
||||
float offy = isRelative ? hist.lastPoint.y : 0f;
|
||||
|
||||
path.quadTo(kx + offx, ky + offy, x + offx, y + offy);
|
||||
hist.setLastPoint(x + offx, y + offy);
|
||||
hist.setLastKnot(kx + offx, ky + offy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumKnotsAdded()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 8:40 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.pathcmd;
|
||||
|
||||
//import org.apache.batik.ext.awt.geom.ExtendedGeneralPath;
|
||||
import java.awt.geom.*;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class QuadraticSmooth extends PathCommand {
|
||||
|
||||
public float x = 0f;
|
||||
public float y = 0f;
|
||||
|
||||
/** Creates a new instance of MoveTo */
|
||||
public QuadraticSmooth() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "T " + x + " " + y;
|
||||
}
|
||||
|
||||
public QuadraticSmooth(boolean isRelative, float x, float y) {
|
||||
super(isRelative);
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
// public void appendPath(ExtendedGeneralPath path, BuildHistory hist)
|
||||
@Override
|
||||
public void appendPath(GeneralPath path, BuildHistory hist)
|
||||
{
|
||||
float offx = isRelative ? hist.lastPoint.x : 0f;
|
||||
float offy = isRelative ? hist.lastPoint.y : 0f;
|
||||
|
||||
float oldKx = hist.lastKnot.x;
|
||||
float oldKy = hist.lastKnot.y;
|
||||
float oldX = hist.lastPoint.x;
|
||||
float oldY = hist.lastPoint.y;
|
||||
//Calc knot as reflection of old knot
|
||||
float kx = oldX * 2f - oldKx;
|
||||
float ky = oldY * 2f - oldKy;
|
||||
|
||||
path.quadTo(kx, ky, x + offx, y + offy);
|
||||
hist.setLastPoint(x + offx, y + offy);
|
||||
hist.setLastKnot(kx, ky);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumKnotsAdded()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 8:40 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.pathcmd;
|
||||
|
||||
//import org.apache.batik.ext.awt.geom.ExtendedGeneralPath;
|
||||
import java.awt.geom.*;
|
||||
|
||||
/**
|
||||
* Finishes a path
|
||||
*
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Terminal extends PathCommand {
|
||||
|
||||
/** Creates a new instance of MoveTo */
|
||||
public Terminal() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Z";
|
||||
}
|
||||
|
||||
|
||||
// public void appendPath(ExtendedGeneralPath path, BuildHistory hist)
|
||||
@Override
|
||||
public void appendPath(GeneralPath path, BuildHistory hist)
|
||||
{
|
||||
path.closePath();
|
||||
hist.setLastPoint(hist.startPoint.x, hist.startPoint.y);
|
||||
hist.setLastKnot(hist.startPoint.x, hist.startPoint.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumKnotsAdded()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 8:40 PM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.pathcmd;
|
||||
|
||||
//import org.apache.batik.ext.awt.geom.ExtendedGeneralPath;
|
||||
import java.awt.geom.*;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class Vertical extends PathCommand {
|
||||
|
||||
public float y = 0f;
|
||||
|
||||
/** Creates a new instance of MoveTo */
|
||||
public Vertical() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "V " + y;
|
||||
}
|
||||
|
||||
public Vertical(boolean isRelative, float y) {
|
||||
super(isRelative);
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
// public void appendPath(ExtendedGeneralPath path, BuildHistory hist)
|
||||
@Override
|
||||
public void appendPath(GeneralPath path, BuildHistory hist)
|
||||
{
|
||||
float offx = hist.lastPoint.x;
|
||||
float offy = isRelative ? hist.lastPoint.y : 0f;
|
||||
|
||||
path.lineTo(offx, y + offy);
|
||||
hist.setLastPoint(offx, y + offy);
|
||||
hist.setLastKnot(offx, y + offy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumKnotsAdded()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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 April 1, 2004, 3:37 AM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.pattern;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.*;
|
||||
import java.awt.image.*;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class PatternPaint implements Paint
|
||||
{
|
||||
BufferedImage source; //Image we're rendering from
|
||||
AffineTransform xform;
|
||||
|
||||
/** Creates a new instance of PatternPaint */
|
||||
public PatternPaint(BufferedImage source, AffineTransform xform)
|
||||
{
|
||||
this.source = source;
|
||||
this.xform = xform;
|
||||
}
|
||||
|
||||
public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, Rectangle2D userBounds, AffineTransform xform, RenderingHints hints)
|
||||
{
|
||||
return new PatternPaintContext(source, deviceBounds, xform, this.xform);
|
||||
}
|
||||
|
||||
public int getTransparency()
|
||||
{
|
||||
return source.getColorModel().getTransparency();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* 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 April 1, 2004, 3:37 AM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.pattern;
|
||||
|
||||
import org.xbib.graphics.svg.SVGConst;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.*;
|
||||
import java.awt.image.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class PatternPaintContext implements PaintContext
|
||||
{
|
||||
BufferedImage source; //Image we're rendering from
|
||||
Rectangle deviceBounds; //int size of rectangle we're rendering to
|
||||
// AffineTransform userXform; //xform from user space to device space
|
||||
// AffineTransform distortXform; //distortion applied to this pattern
|
||||
|
||||
AffineTransform xform; //distortion applied to this pattern
|
||||
|
||||
int sourceWidth;
|
||||
int sourceHeight;
|
||||
|
||||
//Raster we use to build tile
|
||||
BufferedImage buf;
|
||||
|
||||
/** Creates a new instance of PatternPaintContext */
|
||||
public PatternPaintContext(BufferedImage source, Rectangle deviceBounds, AffineTransform userXform, AffineTransform distortXform)
|
||||
{
|
||||
//System.err.println("Bounds " + deviceBounds);
|
||||
this.source = source;
|
||||
this.deviceBounds = deviceBounds;
|
||||
try {
|
||||
// this.distortXform = distortXform.createInverse();
|
||||
// this.userXform = userXform.createInverse();
|
||||
|
||||
// xform = userXform.createInverse();
|
||||
// xform.concatenate(distortXform.createInverse());
|
||||
xform = distortXform.createInverse();
|
||||
xform.concatenate(userXform.createInverse());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e);
|
||||
}
|
||||
|
||||
sourceWidth = source.getWidth();
|
||||
sourceHeight = source.getHeight();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
public ColorModel getColorModel() {
|
||||
return source.getColorModel();
|
||||
}
|
||||
|
||||
public Raster getRaster(int x, int y, int w, int h)
|
||||
{
|
||||
//System.err.println("" + x + ", " + y + ", " + w + ", " + h);
|
||||
if (buf == null || buf.getWidth() != w || buf.getHeight() != h)
|
||||
{
|
||||
buf = new BufferedImage(w, h, source.getType());
|
||||
}
|
||||
|
||||
// Point2D.Float srcPt = new Point2D.Float(), srcPt2 = new Point2D.Float(), destPt = new Point2D.Float();
|
||||
Point2D.Float srcPt = new Point2D.Float(), destPt = new Point2D.Float();
|
||||
for (int j = 0; j < h; j++)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
destPt.setLocation(i + x, j + y);
|
||||
|
||||
xform.transform(destPt, srcPt);
|
||||
|
||||
// userXform.transform(destPt, srcPt2);
|
||||
// distortXform.transform(srcPt2, srcPt);
|
||||
|
||||
int ii = ((int)srcPt.x) % sourceWidth;
|
||||
if (ii < 0) ii += sourceWidth;
|
||||
int jj = ((int)srcPt.y) % sourceHeight;
|
||||
if (jj < 0) jj += sourceHeight;
|
||||
|
||||
buf.setRGB(i, j, source.getRGB(ii, jj));
|
||||
}
|
||||
}
|
||||
|
||||
return buf.getData();
|
||||
}
|
||||
|
||||
public static void main(String[] argv)
|
||||
{
|
||||
int i = -4;
|
||||
System.err.println("Hello " + (i % 4));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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 July 23, 2007
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.util;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public interface Base64Consts
|
||||
{
|
||||
final String BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* 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 July 23, 2007
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.util;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class Base64InputStream extends FilterInputStream implements Base64Consts
|
||||
{
|
||||
static final HashMap<Byte, Integer> lookup64 = new HashMap<Byte, Integer>();
|
||||
static {
|
||||
byte[] ch = BASE64_CHARS.getBytes();
|
||||
for (int i = 0; i < ch.length; i++)
|
||||
{
|
||||
lookup64.put(new Byte(ch[i]), new Integer(i));
|
||||
}
|
||||
}
|
||||
|
||||
int buf;
|
||||
int charsInBuf;
|
||||
|
||||
/** Creates a new instance of Base64InputStream */
|
||||
public Base64InputStream(InputStream in)
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException
|
||||
{
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
int val = read();
|
||||
if (val == -1)
|
||||
{
|
||||
return i == 0 ? -1 : i;
|
||||
}
|
||||
b[off + i] = (byte)val;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int read() throws IOException
|
||||
{
|
||||
if (charsInBuf == 0)
|
||||
{
|
||||
fillBuffer();
|
||||
if (charsInBuf == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (buf >> (--charsInBuf * 8)) & 0xff;
|
||||
}
|
||||
|
||||
private void fillBuffer() throws IOException
|
||||
{
|
||||
//Read next 4 characters
|
||||
int bitsRead = 0;
|
||||
while (bitsRead < 24)
|
||||
{
|
||||
int val = in.read();
|
||||
if (val == -1 || val == '=') break;
|
||||
|
||||
Integer lval = (Integer)lookup64.get(new Byte((byte)val));
|
||||
if (lval == null) continue;
|
||||
|
||||
buf = buf << 6 | lval.byteValue();
|
||||
bitsRead += 6;
|
||||
}
|
||||
|
||||
switch (bitsRead)
|
||||
{
|
||||
case 6:
|
||||
{
|
||||
throw new RuntimeException("Invalid termination of base64 encoding.");
|
||||
}
|
||||
case 12:
|
||||
{
|
||||
buf >>= 4;
|
||||
bitsRead = 8;
|
||||
break;
|
||||
}
|
||||
case 18:
|
||||
{
|
||||
buf >>= 2;
|
||||
bitsRead = 16;
|
||||
break;
|
||||
}
|
||||
case 0:
|
||||
case 24:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
assert false : "Should never encounter other bit counts";
|
||||
}
|
||||
}
|
||||
|
||||
charsInBuf = bitsRead / 8;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* 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 July 23, 2007
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.util;
|
||||
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class Base64OutputStream extends FilterOutputStream implements Base64Consts
|
||||
{
|
||||
int buf;
|
||||
int bitsUsed;
|
||||
int charsPrinted;
|
||||
|
||||
/** Creates a new instance of Base64OutputSream */
|
||||
public Base64OutputStream(OutputStream out)
|
||||
{
|
||||
super(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
writeBits();
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
buf = buf << 8 | (b & 0xff);
|
||||
bitsUsed += 8;
|
||||
if (bitsUsed == 24)
|
||||
{
|
||||
writeBits();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeBits() throws IOException
|
||||
{
|
||||
int padSize;
|
||||
//Pad unused bits with 0
|
||||
switch (bitsUsed)
|
||||
{
|
||||
case 8:
|
||||
{
|
||||
bitsUsed = 12;
|
||||
buf <<= 4;
|
||||
padSize = 2;
|
||||
break;
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
bitsUsed = 18;
|
||||
buf <<= 2;
|
||||
padSize = 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
padSize = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (charsPrinted == 76)
|
||||
{
|
||||
out.write('\r');
|
||||
out.write('\n');
|
||||
charsPrinted = 0;
|
||||
}
|
||||
|
||||
for (; bitsUsed > 0; bitsUsed -= 6)
|
||||
{
|
||||
int b = buf >> (bitsUsed - 6) & 0x3f;
|
||||
out.write(BASE64_CHARS.charAt(b));
|
||||
}
|
||||
|
||||
for (int i = 0; i < padSize; i++)
|
||||
{
|
||||
out.write('=');
|
||||
}
|
||||
|
||||
charsPrinted += 4;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* 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 April 24, 2015
|
||||
*/
|
||||
package org.xbib.graphics.svg.util;
|
||||
|
||||
import org.xbib.graphics.svg.Font;
|
||||
import org.xbib.graphics.svg.FontFace;
|
||||
import org.xbib.graphics.svg.Glyph;
|
||||
import org.xbib.graphics.svg.MissingGlyph;
|
||||
import org.xbib.graphics.svg.Text;
|
||||
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphMetrics;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.font.LineMetrics;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class FontSystem extends Font
|
||||
{
|
||||
java.awt.Font sysFont;
|
||||
|
||||
HashMap<String, Glyph> glyphCache = new HashMap<>();
|
||||
|
||||
static HashSet<String> sysFontNames = new HashSet<>();
|
||||
|
||||
public static boolean checkIfSystemFontExists(String fontName)
|
||||
{
|
||||
if (sysFontNames.isEmpty())
|
||||
{
|
||||
for (String name: GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(Locale.ENGLISH))
|
||||
{
|
||||
sysFontNames.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
return sysFontNames.contains(fontName);
|
||||
}
|
||||
|
||||
public static FontSystem createFont(String[] fontFamilies, int fontStyle, int fontWeight, float fontSize)
|
||||
{
|
||||
for (String fontName: fontFamilies)
|
||||
{
|
||||
String javaFontName = mapJavaFontName(fontName);
|
||||
if (checkIfSystemFontExists(javaFontName))
|
||||
{
|
||||
return new FontSystem(javaFontName, fontStyle, fontWeight, fontSize);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String mapJavaFontName(String fontName)
|
||||
{
|
||||
if ("serif".equals(fontName))
|
||||
{
|
||||
return java.awt.Font.SERIF;
|
||||
}
|
||||
else if ("sans-serif".equals(fontName))
|
||||
{
|
||||
return java.awt.Font.SANS_SERIF;
|
||||
}
|
||||
else if ("monospace".equals(fontName))
|
||||
{
|
||||
return java.awt.Font.MONOSPACED;
|
||||
}
|
||||
return fontName;
|
||||
}
|
||||
|
||||
private FontSystem(String fontFamily, int fontStyle, int fontWeight, float fontSize)
|
||||
{
|
||||
int style;
|
||||
switch (fontStyle)
|
||||
{
|
||||
case Text.TXST_ITALIC:
|
||||
style = java.awt.Font.ITALIC;
|
||||
break;
|
||||
default:
|
||||
style = java.awt.Font.PLAIN;
|
||||
break;
|
||||
}
|
||||
|
||||
int weight;
|
||||
switch (fontWeight)
|
||||
{
|
||||
case Text.TXWE_BOLD:
|
||||
case Text.TXWE_BOLDER:
|
||||
weight = java.awt.Font.BOLD;
|
||||
break;
|
||||
default:
|
||||
weight = java.awt.Font.PLAIN;
|
||||
break;
|
||||
}
|
||||
|
||||
sysFont = new java.awt.Font(fontFamily, style | weight, 1).deriveFont(fontSize);
|
||||
|
||||
FontRenderContext fontRenderContext = new FontRenderContext(null, true, true);
|
||||
LineMetrics lineMetrics = sysFont.getLineMetrics("M", fontRenderContext);
|
||||
|
||||
FontFace face = new FontFace();
|
||||
face.setAscent((int) lineMetrics.getAscent());
|
||||
face.setDescent((int) lineMetrics.getDescent());
|
||||
face.setUnitsPerEm((int) sysFont.getStringBounds("M", fontRenderContext).getWidth());
|
||||
setFontFace(face);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MissingGlyph getGlyph(String unicode)
|
||||
{
|
||||
FontRenderContext frc = new FontRenderContext(null, true, true);
|
||||
GlyphVector vec = sysFont.createGlyphVector(frc, unicode);
|
||||
|
||||
Glyph glyph = (Glyph)glyphCache.get(unicode);
|
||||
if (glyph == null)
|
||||
{
|
||||
glyph = new Glyph();
|
||||
glyph.setPath(vec.getGlyphOutline(0));
|
||||
|
||||
GlyphMetrics gm = vec.getGlyphMetrics(0);
|
||||
glyph.setHorizAdvX(gm.getAdvanceX());
|
||||
glyph.setVertAdvY(gm.getAdvanceY());
|
||||
glyph.setVertOriginX(0);
|
||||
glyph.setVertOriginY(0);
|
||||
|
||||
glyphCache.put(unicode, glyph);
|
||||
}
|
||||
|
||||
return glyph;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
package org.xbib.graphics.svg.util;
|
||||
|
||||
import org.xbib.graphics.svg.Font;
|
||||
import org.xbib.graphics.svg.SVGDiagram;
|
||||
import org.xbib.graphics.svg.SVGElement;
|
||||
import org.xbib.graphics.svg.SVGException;
|
||||
import org.xbib.graphics.svg.Text;
|
||||
import org.xbib.graphics.svg.xml.StyleAttribute;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Utility class for parsing font information of an {@link SVGElement}.
|
||||
*
|
||||
* @author Jannis Weis
|
||||
*/
|
||||
public final class FontUtil
|
||||
{
|
||||
|
||||
private static final String DEFAULT_FONT_FAMILY = "sans-serif";
|
||||
private static final float DEFAULT_FONT_SIZE = 12f;
|
||||
private static final int DEFAULT_LETTER_SPACING = 0;
|
||||
private static final int DEFAULT_FONT_STYLE = Text.TXST_NORMAL;
|
||||
private static final int DEFAULT_FONT_WEIGHT = Text.TXWE_NORMAL;
|
||||
|
||||
private FontUtil() {}
|
||||
|
||||
public final static class FontInfo {
|
||||
public final String[] families;
|
||||
public final float size;
|
||||
public final int style;
|
||||
public final int weight;
|
||||
public final float letterSpacing;
|
||||
|
||||
public FontInfo(String[] families, float size, int style, int weight, float letterSpacing)
|
||||
{
|
||||
this.families = families;
|
||||
this.size = size;
|
||||
this.style = style;
|
||||
this.weight = weight;
|
||||
this.letterSpacing = letterSpacing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof FontInfo)) return false;
|
||||
FontInfo fontInfo = (FontInfo) o;
|
||||
return Float.compare(fontInfo.size, size) == 0
|
||||
&& style == fontInfo.style && weight == fontInfo.weight
|
||||
&& Float.compare(fontInfo.letterSpacing, letterSpacing) == 0
|
||||
&& Arrays.equals(families, fontInfo.families);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int result = Objects.hash(size, style, weight, letterSpacing);
|
||||
result = 31 * result + Arrays.hashCode(families);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static FontInfo parseFontInfo(SVGElement element, StyleAttribute sty) throws SVGException
|
||||
{
|
||||
String fontFamily = DEFAULT_FONT_FAMILY;
|
||||
if (element.getStyle(sty.setName("font-family")))
|
||||
{
|
||||
fontFamily = sty.getStringValue();
|
||||
}
|
||||
|
||||
float fontSize = DEFAULT_FONT_SIZE;
|
||||
if (element.getStyle(sty.setName("font-size")))
|
||||
{
|
||||
fontSize = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
float letterSpacing = DEFAULT_LETTER_SPACING;
|
||||
if (element.getStyle(sty.setName("letter-spacing")))
|
||||
{
|
||||
letterSpacing = sty.getFloatValueWithUnits();
|
||||
}
|
||||
|
||||
int fontStyle = DEFAULT_FONT_STYLE;
|
||||
if (element.getStyle(sty.setName("font-style")))
|
||||
{
|
||||
String s = sty.getStringValue();
|
||||
if ("normal".equals(s))
|
||||
{
|
||||
fontStyle = Text.TXST_NORMAL;
|
||||
} else if ("italic".equals(s))
|
||||
{
|
||||
fontStyle = Text.TXST_ITALIC;
|
||||
} else if ("oblique".equals(s))
|
||||
{
|
||||
fontStyle = Text.TXST_OBLIQUE;
|
||||
}
|
||||
}
|
||||
|
||||
int fontWeight = DEFAULT_FONT_WEIGHT;
|
||||
if (element.getStyle(sty.setName("font-weight")))
|
||||
{
|
||||
String s = sty.getStringValue();
|
||||
if ("normal".equals(s))
|
||||
{
|
||||
fontWeight = Text.TXWE_NORMAL;
|
||||
} else if ("bold".equals(s))
|
||||
{
|
||||
fontWeight = Text.TXWE_BOLD;
|
||||
}
|
||||
}
|
||||
|
||||
return new FontInfo(fontFamily.split(","), fontSize, fontStyle, fontWeight, letterSpacing);
|
||||
}
|
||||
|
||||
public static Font getFont(FontInfo info, SVGDiagram diagram)
|
||||
{
|
||||
return getFont(info.families, info.style, info.weight, info.size, diagram);
|
||||
}
|
||||
|
||||
private static Font getFont(String[] families, int fontStyle, int fontWeight, float fontSize, SVGDiagram diagram)
|
||||
{
|
||||
Font font = null;
|
||||
for (String family : families)
|
||||
{
|
||||
font = diagram.getUniverse().getFont(family);
|
||||
if (font != null) break;
|
||||
}
|
||||
if (font == null)
|
||||
{
|
||||
//Check system fonts
|
||||
font = FontSystem.createFont(families, fontStyle, fontWeight, fontSize);
|
||||
}
|
||||
if (font == null)
|
||||
{
|
||||
Logger.getLogger(FontSystem.class.getName())
|
||||
.log(Level.WARNING, "Could not create font " + Arrays.toString(families));
|
||||
String[] defaultFont = new String[]{ FontUtil.DEFAULT_FONT_FAMILY };
|
||||
font = FontSystem.createFont(defaultFont, fontStyle, fontWeight, fontSize);
|
||||
}
|
||||
return font;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 April 24, 2015
|
||||
*/
|
||||
package org.xbib.graphics.svg.util;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kitfox
|
||||
*/
|
||||
public class TextBuilder
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* 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 January 26, 2004, 4:34 AM
|
||||
*/
|
||||
|
||||
package org.xbib.graphics.svg.xml;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Mark McKay
|
||||
* @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
|
||||
*/
|
||||
public class ColorTable
|
||||
{
|
||||
|
||||
static final Map<String, Color> colorTable;
|
||||
static {
|
||||
HashMap<String, Color> table = new HashMap<String, Color>();
|
||||
|
||||
//We really should be interpreting the currentColor keyword as
|
||||
// a reference to the referring node's color, but this quick hack
|
||||
// will stop the program from crashing.
|
||||
table.put("currentcolor", new Color(0x0));
|
||||
|
||||
table.put("aliceblue", new Color(0xf0f8ff));
|
||||
table.put("antiquewhite", new Color(0xfaebd7));
|
||||
table.put("aqua", new Color(0x00ffff));
|
||||
table.put("aquamarine", new Color(0x7fffd4));
|
||||
table.put("azure", new Color(0xf0ffff));
|
||||
table.put("beige", new Color(0xf5f5dc));
|
||||
table.put("bisque", new Color(0xffe4c4));
|
||||
table.put("black", new Color(0x000000));
|
||||
table.put("blanchedalmond", new Color(0xffebcd));
|
||||
table.put("blue", new Color(0x0000ff));
|
||||
table.put("blueviolet", new Color(0x8a2be2));
|
||||
table.put("brown", new Color(0xa52a2a));
|
||||
table.put("burlywood", new Color(0xdeb887));
|
||||
table.put("cadetblue", new Color(0x5f9ea0));
|
||||
table.put("chartreuse", new Color(0x7fff00));
|
||||
table.put("chocolate", new Color(0xd2691e));
|
||||
table.put("coral", new Color(0xff7f50));
|
||||
table.put("cornflowerblue", new Color(0x6495ed));
|
||||
table.put("cornsilk", new Color(0xfff8dc));
|
||||
table.put("crimson", new Color(0xdc143c));
|
||||
table.put("cyan", new Color(0x00ffff));
|
||||
table.put("darkblue", new Color(0x00008b));
|
||||
table.put("darkcyan", new Color(0x008b8b));
|
||||
table.put("darkgoldenrod", new Color(0xb8860b));
|
||||
table.put("darkgray", new Color(0xa9a9a9));
|
||||
table.put("darkgreen", new Color(0x006400));
|
||||
table.put("darkkhaki", new Color(0xbdb76b));
|
||||
table.put("darkmagenta", new Color(0x8b008b));
|
||||
table.put("darkolivegreen", new Color(0x556b2f));
|
||||
table.put("darkorange", new Color(0xff8c00));
|
||||
table.put("darkorchid", new Color(0x9932cc));
|
||||
table.put("darkred", new Color(0x8b0000));
|
||||
table.put("darksalmon", new Color(0xe9967a));
|
||||
table.put("darkseagreen", new Color(0x8fbc8f));
|
||||
table.put("darkslateblue", new Color(0x483d8b));
|
||||
table.put("darkslategray", new Color(0x2f4f4f));
|
||||
table.put("darkturquoise", new Color(0x00ced1));
|
||||
table.put("darkviolet", new Color(0x9400d3));
|
||||
table.put("deeppink", new Color(0xff1493));
|
||||
table.put("deepskyblue", new Color(0x00bfff));
|
||||
table.put("dimgray", new Color(0x696969));
|
||||
table.put("dodgerblue", new Color(0x1e90ff));
|
||||
table.put("feldspar", new Color(0xd19275));
|
||||
table.put("firebrick", new Color(0xb22222));
|
||||
table.put("floralwhite", new Color(0xfffaf0));
|
||||
table.put("forestgreen", new Color(0x228b22));
|
||||
table.put("fuchsia", new Color(0xff00ff));
|
||||
table.put("gainsboro", new Color(0xdcdcdc));
|
||||
table.put("ghostwhite", new Color(0xf8f8ff));
|
||||
table.put("gold", new Color(0xffd700));
|
||||
table.put("goldenrod", new Color(0xdaa520));
|
||||
table.put("gray", new Color(0x808080));
|
||||
table.put("green", new Color(0x008000));
|
||||
table.put("greenyellow", new Color(0xadff2f));
|
||||
table.put("honeydew", new Color(0xf0fff0));
|
||||
table.put("hotpink", new Color(0xff69b4));
|
||||
table.put("indianred", new Color(0xcd5c5c));
|
||||
table.put("indigo", new Color(0x4b0082));
|
||||
table.put("ivory", new Color(0xfffff0));
|
||||
table.put("khaki", new Color(0xf0e68c));
|
||||
table.put("lavender", new Color(0xe6e6fa));
|
||||
table.put("lavenderblush", new Color(0xfff0f5));
|
||||
table.put("lawngreen", new Color(0x7cfc00));
|
||||
table.put("lemonchiffon", new Color(0xfffacd));
|
||||
table.put("lightblue", new Color(0xadd8e6));
|
||||
table.put("lightcoral", new Color(0xf08080));
|
||||
table.put("lightcyan", new Color(0xe0ffff));
|
||||
table.put("lightgoldenrodyellow", new Color(0xfafad2));
|
||||
table.put("lightgrey", new Color(0xd3d3d3));
|
||||
table.put("lightgreen", new Color(0x90ee90));
|
||||
table.put("lightpink", new Color(0xffb6c1));
|
||||
table.put("lightsalmon", new Color(0xffa07a));
|
||||
table.put("lightseagreen", new Color(0x20b2aa));
|
||||
table.put("lightskyblue", new Color(0x87cefa));
|
||||
table.put("lightslateblue", new Color(0x8470ff));
|
||||
table.put("lightslategray", new Color(0x778899));
|
||||
table.put("lightsteelblue", new Color(0xb0c4de));
|
||||
table.put("lightyellow", new Color(0xffffe0));
|
||||
table.put("lime", new Color(0x00ff00));
|
||||
table.put("limegreen", new Color(0x32cd32));
|
||||
table.put("linen", new Color(0xfaf0e6));
|
||||
table.put("magenta", new Color(0xff00ff));
|
||||
table.put("maroon", new Color(0x800000));
|
||||
table.put("mediumaquamarine", new Color(0x66cdaa));
|
||||
table.put("mediumblue", new Color(0x0000cd));
|
||||
table.put("mediumorchid", new Color(0xba55d3));
|
||||
table.put("mediumpurple", new Color(0x9370d8));
|
||||
table.put("mediumseagreen", new Color(0x3cb371));
|
||||
table.put("mediumslateblue", new Color(0x7b68ee));
|
||||
table.put("mediumspringgreen", new Color(0x00fa9a));
|
||||
table.put("mediumturquoise", new Color(0x48d1cc));
|
||||
table.put("mediumvioletred", new Color(0xc71585));
|
||||
table.put("midnightblue", new Color(0x191970));
|
||||
table.put("mintcream", new Color(0xf5fffa));
|
||||
table.put("mistyrose", new Color(0xffe4e1));
|
||||
table.put("moccasin", new Color(0xffe4b5));
|
||||
table.put("navajowhite", new Color(0xffdead));
|
||||
table.put("navy", new Color(0x000080));
|
||||
table.put("oldlace", new Color(0xfdf5e6));
|
||||
table.put("olive", new Color(0x808000));
|
||||
table.put("olivedrab", new Color(0x6b8e23));
|
||||
table.put("orange", new Color(0xffa500));
|
||||
table.put("orangered", new Color(0xff4500));
|
||||
table.put("orchid", new Color(0xda70d6));
|
||||
table.put("palegoldenrod", new Color(0xeee8aa));
|
||||
table.put("palegreen", new Color(0x98fb98));
|
||||
table.put("paleturquoise", new Color(0xafeeee));
|
||||
table.put("palevioletred", new Color(0xd87093));
|
||||
table.put("papayawhip", new Color(0xffefd5));
|
||||
table.put("peachpuff", new Color(0xffdab9));
|
||||
table.put("peru", new Color(0xcd853f));
|
||||
table.put("pink", new Color(0xffc0cb));
|
||||
table.put("plum", new Color(0xdda0dd));
|
||||
table.put("powderblue", new Color(0xb0e0e6));
|
||||
table.put("purple", new Color(0x800080));
|
||||
table.put("red", new Color(0xff0000));
|
||||
table.put("rosybrown", new Color(0xbc8f8f));
|
||||
table.put("royalblue", new Color(0x4169e1));
|
||||
table.put("saddlebrown", new Color(0x8b4513));
|
||||
table.put("salmon", new Color(0xfa8072));
|
||||
table.put("sandybrown", new Color(0xf4a460));
|
||||
table.put("seagreen", new Color(0x2e8b57));
|
||||
table.put("seashell", new Color(0xfff5ee));
|
||||
table.put("sienna", new Color(0xa0522d));
|
||||
table.put("silver", new Color(0xc0c0c0));
|
||||
table.put("skyblue", new Color(0x87ceeb));
|
||||
table.put("slateblue", new Color(0x6a5acd));
|
||||
table.put("slategray", new Color(0x708090));
|
||||
table.put("snow", new Color(0xfffafa));
|
||||
table.put("springgreen", new Color(0x00ff7f));
|
||||
table.put("steelblue", new Color(0x4682b4));
|
||||
table.put("tan", new Color(0xd2b48c));
|
||||
table.put("teal", new Color(0x008080));
|
||||
table.put("thistle", new Color(0xd8bfd8));
|
||||
table.put("tomato", new Color(0xff6347));
|
||||
table.put("turquoise", new Color(0x40e0d0));
|
||||
table.put("violet", new Color(0xee82ee));
|
||||
table.put("violetred", new Color(0xd02090));
|
||||
table.put("wheat", new Color(0xf5deb3));
|
||||
table.put("white", new Color(0xffffff));
|
||||
table.put("whitesmoke", new Color(0xf5f5f5));
|
||||
table.put("yellow", new Color(0xffff00));
|
||||
table.put("yellowgreen", new Color(0x9acd32));
|
||||
|
||||
colorTable = Collections.unmodifiableMap(table);
|
||||
}
|
||||
|
||||
static ColorTable singleton = new ColorTable();
|
||||
|
||||
/** Creates a new instance of ColorTable */
|
||||
protected ColorTable() {
|
||||
// buildColorList();
|
||||
}
|
||||
|
||||
static public ColorTable instance() { return singleton; }
|
||||
|
||||
public Color lookupColor(String name) {
|
||||
return colorTable.get(name.toLowerCase());
|
||||
}
|
||||
|
||||
public static Color parseColor(String val)
|
||||
{
|
||||
Color retVal = null;
|
||||
|
||||
if ("".equals(val))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (val.charAt(0) == '#')
|
||||
{
|
||||
String hexStrn = val.substring(1);
|
||||
|
||||
if (hexStrn.length() == 3)
|
||||
{
|
||||
hexStrn = "" + hexStrn.charAt(0) + hexStrn.charAt(0) + hexStrn.charAt(1) + hexStrn.charAt(1) + hexStrn.charAt(2) + hexStrn.charAt(2);
|
||||
}
|
||||
int hexVal = parseHex(hexStrn);
|
||||
|
||||
retVal = new Color(hexVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
final String number = "\\s*(((\\d+)(\\.\\d*)?)|(\\.\\d+))(%)?\\s*";
|
||||
final Matcher rgbMatch = Pattern.compile("rgb\\(" + number + "," + number + "," + number + "\\)", Pattern.CASE_INSENSITIVE).matcher("");
|
||||
|
||||
rgbMatch.reset(val);
|
||||
if (rgbMatch.matches())
|
||||
{
|
||||
float rr = Float.parseFloat(rgbMatch.group(1));
|
||||
float gg = Float.parseFloat(rgbMatch.group(7));
|
||||
float bb = Float.parseFloat(rgbMatch.group(13));
|
||||
rr /= "%".equals(rgbMatch.group(6)) ? 100 : 255;
|
||||
gg /= "%".equals(rgbMatch.group(12)) ? 100 : 255;
|
||||
bb /= "%".equals(rgbMatch.group(18)) ? 100 : 255;
|
||||
retVal = new Color(rr, gg, bb);
|
||||
}
|
||||
else
|
||||
{
|
||||
Color lookupCol = ColorTable.instance().lookupColor(val);
|
||||
if (lookupCol != null) retVal = lookupCol;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static int parseHex(String val)
|
||||
{
|
||||
int retVal = 0;
|
||||
|
||||
for (int i = 0; i < val.length(); i++)
|
||||
{
|
||||
retVal <<= 4;
|
||||
|
||||
char ch = val.charAt(i);
|
||||
if (ch >= '0' && ch <= '9')
|
||||
{
|
||||
retVal |= ch - '0';
|
||||
}
|
||||
else if (ch >= 'a' && ch <= 'z')
|
||||
{
|
||||
retVal |= ch - 'a' + 10;
|
||||
}
|
||||
else if (ch >= 'A' && ch <= 'Z')
|
||||
{
|
||||
retVal |= ch - 'A' + 10;
|
||||
}
|
||||
else throw new RuntimeException();
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue