From 091a1e0179cb264cc2cab6e3b11ea31045c8536d Mon Sep 17 00:00:00 2001 From: kitfox Date: Tue, 29 May 2007 23:33:23 +0000 Subject: Restoring SVG Salamander to it's original code base, and updating build scripts. git-svn-id: https://svn.java.net/svn/svgsalamander~svn/trunk/svg-core@36 7dc7fa77-23fb-e6ad-8e2e-c86bd48ed22b --- src/main/java/com/kitfox/svg/Tspan.java | 380 ++++++++++++++++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 src/main/java/com/kitfox/svg/Tspan.java (limited to 'src/main/java/com/kitfox/svg/Tspan.java') diff --git a/src/main/java/com/kitfox/svg/Tspan.java b/src/main/java/com/kitfox/svg/Tspan.java new file mode 100644 index 0000000..bffa6b8 --- /dev/null +++ b/src/main/java/com/kitfox/svg/Tspan.java @@ -0,0 +1,380 @@ +/* + * Stop.java + * + * + * The Salamander Project - 2D and 3D graphics libraries in Java + * Copyright (C) 2004 Mark McKay + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * 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 com.kitfox.svg; + +import com.kitfox.svg.xml.StyleAttribute; +import java.awt.*; +import java.awt.font.*; +import java.awt.geom.*; +import java.util.*; + +import com.kitfox.svg.xml.*; +import org.xml.sax.*; + +//import org.apache.batik.ext.awt.geom.ExtendedGeneralPath; + +/** + * @author Mark McKay + * @author Mark McKay + */ +public class Tspan extends ShapeElement { + + float[] x = null; + float[] y = null; + float[] dx = null; + float[] dy = null; + float[] rotate = null; + + private String text = ""; + + float cursorX; + float cursorY; + +// Shape tspanShape; + + /** Creates a new instance of Stop */ + public Tspan() { + } + + public float getCursorX() { return cursorX; } + public float getCursorY() { return cursorY; } + + public void setCursorX(float cursorX) + { + this.cursorX = cursorX; + } + + public void setCursorY(float cursorY) + { + this.cursorY = cursorY; + } +/* + 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 dx = attrs.getValue("dx"); + String dy = attrs.getValue("dy"); + String rotate = attrs.getValue("rotate"); + + if (x != null) this.x = XMLParseUtil.parseFloatList(x); + if (y != null) this.y = XMLParseUtil.parseFloatList(y); + if (dx != null) this.dx = XMLParseUtil.parseFloatList(dx); + if (dy != null) this.dy = XMLParseUtil.parseFloatList(dy); + if (rotate != null) + { + this.rotate = XMLParseUtil.parseFloatList(rotate); + for (int i = 0; i < this.rotate.length; i++) + this.rotate[i] = (float)Math.toRadians(this.rotate[i]); + } + } + */ + + /** + * Called during load process to add text scanned within a tag + */ + public void loaderAddText(SVGLoaderHelper helper, String text) + { + this.text += text; + } + + + protected void build() throws SVGException + { + super.build(); + + StyleAttribute sty = new StyleAttribute(); + + if (getPres(sty.setName("x"))) x = sty.getFloatList(); + + if (getPres(sty.setName("y"))) y = sty.getFloatList(); + + if (getPres(sty.setName("dx"))) dx = sty.getFloatList(); + + if (getPres(sty.setName("dy"))) dy = sty.getFloatList(); + + 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]); + } + + } + } + + public void addShape(GeneralPath addShape) throws SVGException + { + if (x != null) + { + cursorX = x[0]; + cursorY = y[0]; + } + else if (dx != null) + { + cursorX += dx[0]; + cursorY += dy[0]; + } + + StyleAttribute sty = new StyleAttribute(); + + String fontFamily = null; + if (getStyle(sty.setName("font-family"))) + { + fontFamily = sty.getStringValue(); + } + + + float fontSize = 12f; + if (getStyle(sty.setName("font-size"))) + { + fontSize = sty.getFloatValueWithUnits(); + } + + //Get font + Font font = diagram.getUniverse().getFont(fontFamily); + if (font == null) + { + addShapeSysFont(addShape, font, fontFamily, fontSize); + return; + } + + FontFace fontFace = font.getFontFace(); + int ascent = fontFace.getAscent(); + float fontScale = fontSize / (float)ascent; + + AffineTransform xform = new AffineTransform(); + + strokeWidthScalar = 1f / fontScale; + + int posPtr = 1; + + for (int i = 0; i < text.length(); i++) + { + xform.setToIdentity(); + xform.setToTranslation(cursorX, cursorY); + xform.scale(fontScale, fontScale); + if (rotate != null) xform.rotate(rotate[posPtr]); + + String unicode = text.substring(i, i + 1); + MissingGlyph glyph = font.getGlyph(unicode); + + Shape path = glyph.getPath(); + if (path != null) + { + path = xform.createTransformedShape(path); + addShape.append(path, false); + } + + if (x != null && posPtr < x.length) + { + cursorX = x[posPtr]; + cursorY = y[posPtr++]; + } + else if (dx != null && posPtr < dx.length) + { + cursorX += dx[posPtr]; + cursorY += dy[posPtr++]; + } + + cursorX += fontScale * glyph.getHorizAdvX(); + } + + strokeWidthScalar = 1f; + } + + private void addShapeSysFont(GeneralPath addShape, Font font, String fontFamily, float fontSize) + { + java.awt.Font sysFont = new java.awt.Font(fontFamily, java.awt.Font.PLAIN, (int)fontSize); + + FontRenderContext frc = new FontRenderContext(null, true, true); + GlyphVector textVector = sysFont.createGlyphVector(frc, text); + + AffineTransform xform = new AffineTransform(); + + int posPtr = 1; + for (int i = 0; i < text.length(); i++) + { + xform.setToIdentity(); + xform.setToTranslation(cursorX, cursorY); + if (rotate != null) xform.rotate(rotate[Math.min(i, rotate.length - 1)]); + + String unicode = text.substring(i, i + 1); + Shape glyphOutline = textVector.getGlyphOutline(i); + GlyphMetrics glyphMetrics = textVector.getGlyphMetrics(i); + + glyphOutline = xform.createTransformedShape(glyphOutline); + addShape.append(glyphOutline, false); + + if (x != null && posPtr < x.length) + { + cursorX = x[posPtr]; + cursorY = y[posPtr++]; + } + else if (dx != null && posPtr < dx.length) + { + cursorX += dx[posPtr]; + cursorY += dy[posPtr++]; + } + } + } + + public void render(Graphics2D g) throws SVGException + { + if (x != null) + { + cursorX = x[0]; + cursorY = y[0]; + } + else if (dx != null) + { + cursorX += dx[0]; + cursorY += dy[0]; + } + + StyleAttribute sty = new StyleAttribute(); + + String fontFamily = null; + if (getPres(sty.setName("font-family"))) + { + fontFamily = sty.getStringValue(); + } + + + float fontSize = 12f; + if (getPres(sty.setName("font-size"))) + { + fontSize = sty.getFloatValueWithUnits(); + } + + //Get font + Font font = diagram.getUniverse().getFont(fontFamily); + if (font == null) + { + System.err.println("Could not load font"); + java.awt.Font sysFont = new java.awt.Font(fontFamily, java.awt.Font.PLAIN, (int)fontSize); + renderSysFont(g, sysFont); + return; + } + + + FontFace fontFace = font.getFontFace(); + int ascent = fontFace.getAscent(); + float fontScale = fontSize / (float)ascent; + + AffineTransform oldXform = g.getTransform(); + AffineTransform xform = new AffineTransform(); + + strokeWidthScalar = 1f / fontScale; + + int posPtr = 1; + + for (int i = 0; i < text.length(); i++) + { + xform.setToTranslation(cursorX, cursorY); + xform.scale(fontScale, fontScale); + g.transform(xform); + + String unicode = text.substring(i, i + 1); + MissingGlyph glyph = font.getGlyph(unicode); + + Shape path = glyph.getPath(); + if (path != null) + { + renderShape(g, path); + } + else glyph.render(g); + + if (x != null && posPtr < x.length) + { + cursorX = x[posPtr]; + cursorY = y[posPtr++]; + } + else if (dx != null && posPtr < dx.length) + { + cursorX += dx[posPtr]; + cursorY += dy[posPtr++]; + } + + cursorX += fontScale * glyph.getHorizAdvX(); + + g.setTransform(oldXform); + } + + strokeWidthScalar = 1f; + } + + protected void renderSysFont(Graphics2D g, java.awt.Font font) throws SVGException + { + int posPtr = 1; + FontRenderContext frc = g.getFontRenderContext(); + + Shape textShape = font.createGlyphVector(frc, text).getOutline(cursorX, cursorY); + renderShape(g, textShape); + Rectangle2D rect = font.getStringBounds(text, frc); + cursorX += (float)rect.getWidth(); + } + + public Shape getShape() + { + return null; + //return shapeToParent(tspanShape); + } + + public Rectangle2D getBoundingBox() + { + return null; + //return boundsToParent(tspanShape.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 + */ + public boolean updateTime(double curTime) throws SVGException + { + //Tspan does not change + return false; + } + + public String getText() + { + return text; + } + + public void setText(String text) + { + this.text = text; + } +} -- cgit v1.2.3-55-g7522