source: josm/trunk/src/com/kitfox/svg/Tspan.java@ 4656

Last change on this file since 4656 was 4256, checked in by bastiK, 13 years ago

see #6560 - basic svg support, includes kitfox svgsalamander, r 98, patched

File size: 10.8 KB
Line 
1/*
2 * Stop.java
3 *
4 *
5 * The Salamander Project - 2D and 3D graphics libraries in Java
6 * Copyright (C) 2004 Mark McKay
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * Mark McKay can be contacted at mark@kitfox.com. Salamander and other
23 * projects can be found at http://www.kitfox.com
24 *
25 * Created on January 26, 2004, 1:56 AM
26 */
27
28package com.kitfox.svg;
29
30import com.kitfox.svg.xml.StyleAttribute;
31import java.awt.*;
32import java.awt.font.*;
33import java.awt.geom.*;
34import java.util.*;
35
36import com.kitfox.svg.xml.*;
37import org.xml.sax.*;
38
39//import org.apache.batik.ext.awt.geom.ExtendedGeneralPath;
40
41/**
42 * @author Mark McKay
43 * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
44 */
45public class Tspan extends ShapeElement {
46
47 float[] x = null;
48 float[] y = null;
49 float[] dx = null;
50 float[] dy = null;
51 float[] rotate = null;
52
53 private String text = "";
54
55 float cursorX;
56 float cursorY;
57
58// Shape tspanShape;
59
60 /** Creates a new instance of Stop */
61 public Tspan() {
62 }
63
64 public float getCursorX() { return cursorX; }
65 public float getCursorY() { return cursorY; }
66
67 public void setCursorX(float cursorX)
68 {
69 this.cursorX = cursorX;
70 }
71
72 public void setCursorY(float cursorY)
73 {
74 this.cursorY = cursorY;
75 }
76/*
77 public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent)
78 {
79 //Load style string
80 super.loaderStartElement(helper, attrs, parent);
81
82 String x = attrs.getValue("x");
83 String y = attrs.getValue("y");
84 String dx = attrs.getValue("dx");
85 String dy = attrs.getValue("dy");
86 String rotate = attrs.getValue("rotate");
87
88 if (x != null) this.x = XMLParseUtil.parseFloatList(x);
89 if (y != null) this.y = XMLParseUtil.parseFloatList(y);
90 if (dx != null) this.dx = XMLParseUtil.parseFloatList(dx);
91 if (dy != null) this.dy = XMLParseUtil.parseFloatList(dy);
92 if (rotate != null)
93 {
94 this.rotate = XMLParseUtil.parseFloatList(rotate);
95 for (int i = 0; i < this.rotate.length; i++)
96 this.rotate[i] = (float)Math.toRadians(this.rotate[i]);
97 }
98 }
99 */
100
101 /**
102 * Called during load process to add text scanned within a tag
103 */
104 public void loaderAddText(SVGLoaderHelper helper, String text)
105 {
106 this.text += text;
107 }
108
109
110 protected void build() throws SVGException
111 {
112 super.build();
113
114 StyleAttribute sty = new StyleAttribute();
115
116 if (getPres(sty.setName("x"))) x = sty.getFloatList();
117
118 if (getPres(sty.setName("y"))) y = sty.getFloatList();
119
120 if (getPres(sty.setName("dx"))) dx = sty.getFloatList();
121
122 if (getPres(sty.setName("dy"))) dy = sty.getFloatList();
123
124 if (getPres(sty.setName("rotate")))
125 {
126 rotate = sty.getFloatList();
127 for (int i = 0; i < this.rotate.length; i++)
128 {
129 rotate[i] = (float)Math.toRadians(this.rotate[i]);
130 }
131
132 }
133 }
134
135 public void addShape(GeneralPath addShape) throws SVGException
136 {
137 if (x != null)
138 {
139 cursorX = x[0];
140 cursorY = y[0];
141 }
142 else if (dx != null)
143 {
144 cursorX += dx[0];
145 cursorY += dy[0];
146 }
147
148 StyleAttribute sty = new StyleAttribute();
149
150 String fontFamily = null;
151 if (getStyle(sty.setName("font-family")))
152 {
153 fontFamily = sty.getStringValue();
154 }
155
156
157 float fontSize = 12f;
158 if (getStyle(sty.setName("font-size")))
159 {
160 fontSize = sty.getFloatValueWithUnits();
161 }
162
163 //Get font
164 Font font = diagram.getUniverse().getFont(fontFamily);
165 if (font == null)
166 {
167 addShapeSysFont(addShape, font, fontFamily, fontSize);
168 return;
169 }
170
171 FontFace fontFace = font.getFontFace();
172 int ascent = fontFace.getAscent();
173 float fontScale = fontSize / (float)ascent;
174
175 AffineTransform xform = new AffineTransform();
176
177 strokeWidthScalar = 1f / fontScale;
178
179 int posPtr = 1;
180
181 for (int i = 0; i < text.length(); i++)
182 {
183 xform.setToIdentity();
184 xform.setToTranslation(cursorX, cursorY);
185 xform.scale(fontScale, fontScale);
186 if (rotate != null) xform.rotate(rotate[posPtr]);
187
188 String unicode = text.substring(i, i + 1);
189 MissingGlyph glyph = font.getGlyph(unicode);
190
191 Shape path = glyph.getPath();
192 if (path != null)
193 {
194 path = xform.createTransformedShape(path);
195 addShape.append(path, false);
196 }
197
198 if (x != null && posPtr < x.length)
199 {
200 cursorX = x[posPtr];
201 cursorY = y[posPtr++];
202 }
203 else if (dx != null && posPtr < dx.length)
204 {
205 cursorX += dx[posPtr];
206 cursorY += dy[posPtr++];
207 }
208
209 cursorX += fontScale * glyph.getHorizAdvX();
210 }
211
212 strokeWidthScalar = 1f;
213 }
214
215 private void addShapeSysFont(GeneralPath addShape, Font font, String fontFamily, float fontSize)
216 {
217 java.awt.Font sysFont = new java.awt.Font(fontFamily, java.awt.Font.PLAIN, (int)fontSize);
218
219 FontRenderContext frc = new FontRenderContext(null, true, true);
220 GlyphVector textVector = sysFont.createGlyphVector(frc, text);
221
222 AffineTransform xform = new AffineTransform();
223
224 int posPtr = 1;
225 for (int i = 0; i < text.length(); i++)
226 {
227 xform.setToIdentity();
228 xform.setToTranslation(cursorX, cursorY);
229 if (rotate != null) xform.rotate(rotate[Math.min(i, rotate.length - 1)]);
230
231 String unicode = text.substring(i, i + 1);
232 Shape glyphOutline = textVector.getGlyphOutline(i);
233 GlyphMetrics glyphMetrics = textVector.getGlyphMetrics(i);
234
235 glyphOutline = xform.createTransformedShape(glyphOutline);
236 addShape.append(glyphOutline, false);
237
238 if (x != null && posPtr < x.length)
239 {
240 cursorX = x[posPtr];
241 cursorY = y[posPtr++];
242 }
243 else if (dx != null && posPtr < dx.length)
244 {
245 cursorX += dx[posPtr];
246 cursorY += dy[posPtr++];
247 }
248 }
249 }
250
251 public void render(Graphics2D g) throws SVGException
252 {
253 if (x != null)
254 {
255 cursorX = x[0];
256 cursorY = y[0];
257 }
258 else if (dx != null)
259 {
260 cursorX += dx[0];
261 cursorY += dy[0];
262 }
263
264 StyleAttribute sty = new StyleAttribute();
265
266 String fontFamily = null;
267 if (getPres(sty.setName("font-family")))
268 {
269 fontFamily = sty.getStringValue();
270 }
271
272
273 float fontSize = 12f;
274 if (getPres(sty.setName("font-size")))
275 {
276 fontSize = sty.getFloatValueWithUnits();
277 }
278
279 //Get font
280 Font font = diagram.getUniverse().getFont(fontFamily);
281 if (font == null)
282 {
283 System.err.println("Could not load font");
284 java.awt.Font sysFont = new java.awt.Font(fontFamily, java.awt.Font.PLAIN, (int)fontSize);
285 renderSysFont(g, sysFont);
286 return;
287 }
288
289
290 FontFace fontFace = font.getFontFace();
291 int ascent = fontFace.getAscent();
292 float fontScale = fontSize / (float)ascent;
293
294 AffineTransform oldXform = g.getTransform();
295 AffineTransform xform = new AffineTransform();
296
297 strokeWidthScalar = 1f / fontScale;
298
299 int posPtr = 1;
300
301 for (int i = 0; i < text.length(); i++)
302 {
303 xform.setToTranslation(cursorX, cursorY);
304 xform.scale(fontScale, fontScale);
305 g.transform(xform);
306
307 String unicode = text.substring(i, i + 1);
308 MissingGlyph glyph = font.getGlyph(unicode);
309
310 Shape path = glyph.getPath();
311 if (path != null)
312 {
313 renderShape(g, path);
314 }
315 else glyph.render(g);
316
317 if (x != null && posPtr < x.length)
318 {
319 cursorX = x[posPtr];
320 cursorY = y[posPtr++];
321 }
322 else if (dx != null && posPtr < dx.length)
323 {
324 cursorX += dx[posPtr];
325 cursorY += dy[posPtr++];
326 }
327
328 cursorX += fontScale * glyph.getHorizAdvX();
329
330 g.setTransform(oldXform);
331 }
332
333 strokeWidthScalar = 1f;
334 }
335
336 protected void renderSysFont(Graphics2D g, java.awt.Font font) throws SVGException
337 {
338 int posPtr = 1;
339 FontRenderContext frc = g.getFontRenderContext();
340
341 Shape textShape = font.createGlyphVector(frc, text).getOutline(cursorX, cursorY);
342 renderShape(g, textShape);
343 Rectangle2D rect = font.getStringBounds(text, frc);
344 cursorX += (float)rect.getWidth();
345 }
346
347 public Shape getShape()
348 {
349 return null;
350 //return shapeToParent(tspanShape);
351 }
352
353 public Rectangle2D getBoundingBox()
354 {
355 return null;
356 //return boundsToParent(tspanShape.getBounds2D());
357 }
358
359 /**
360 * Updates all attributes in this diagram associated with a time event.
361 * Ie, all attributes with track information.
362 * @return - true if this node has changed state as a result of the time
363 * update
364 */
365 public boolean updateTime(double curTime) throws SVGException
366 {
367 //Tspan does not change
368 return false;
369 }
370
371 public String getText()
372 {
373 return text;
374 }
375
376 public void setText(String text)
377 {
378 this.text = text;
379 }
380}
Note: See TracBrowser for help on using the repository browser.