source: josm/trunk/src/com/kitfox/svg/SVGRoot.java@ 6031

Last change on this file since 6031 was 6002, checked in by Don-vip, 12 years ago

fix #8742 - update svgsalamander to release 0.1.18+patch (fix bug SVGSALAMANDER-26) -> allow to open more SVG files

File size: 12.0 KB
Line 
1/*
2 * SVG Salamander
3 * Copyright (c) 2004, Mark McKay
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or
7 * without modification, are permitted provided that the following
8 * conditions are met:
9 *
10 * - Redistributions of source code must retain the above
11 * copyright notice, this list of conditions and the following
12 * disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials
16 * provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Mark McKay can be contacted at mark@kitfox.com. Salamander and other
32 * projects can be found at http://www.kitfox.com
33 *
34 * Created on February 18, 2004, 5:33 PM
35 */
36
37package com.kitfox.svg;
38
39import com.kitfox.svg.xml.NumberWithUnits;
40import com.kitfox.svg.xml.StyleAttribute;
41import com.kitfox.svg.xml.StyleSheet;
42import java.awt.Graphics2D;
43import java.awt.Rectangle;
44import java.awt.Shape;
45import java.awt.geom.AffineTransform;
46import java.awt.geom.Rectangle2D;
47
48/**
49 * The root element of an SVG tree.
50 *
51 * @author Mark McKay
52 * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
53 */
54public class SVGRoot extends Group
55{
56 public static final String TAG_NAME = "svg";
57
58 NumberWithUnits x;
59 NumberWithUnits y;
60 NumberWithUnits width;
61 NumberWithUnits height;
62
63 Rectangle2D.Float viewBox = null;
64
65 public static final int PA_X_NONE = 0;
66 public static final int PA_X_MIN = 1;
67 public static final int PA_X_MID = 2;
68 public static final int PA_X_MAX = 3;
69
70 public static final int PA_Y_NONE = 0;
71 public static final int PA_Y_MIN = 1;
72 public static final int PA_Y_MID = 2;
73 public static final int PA_Y_MAX = 3;
74
75 public static final int PS_MEET = 0;
76 public static final int PS_SLICE = 1;
77
78 int parSpecifier = PS_MEET;
79 int parAlignX = PA_X_MID;
80 int parAlignY = PA_Y_MID;
81
82 final AffineTransform viewXform = new AffineTransform();
83 final Rectangle2D.Float clipRect = new Rectangle2D.Float();
84
85 private StyleSheet styleSheet;
86
87 /** Creates a new instance of SVGRoot */
88 public SVGRoot()
89 {
90 }
91
92 public String getTagName()
93 {
94 return TAG_NAME;
95 }
96
97 public void build() throws SVGException
98 {
99 super.build();
100
101 StyleAttribute sty = new StyleAttribute();
102
103 if (getPres(sty.setName("x")))
104 {
105 x = sty.getNumberWithUnits();
106 }
107
108 if (getPres(sty.setName("y")))
109 {
110 y = sty.getNumberWithUnits();
111 }
112
113 if (getPres(sty.setName("width")))
114 {
115 width = sty.getNumberWithUnits();
116 }
117
118 if (getPres(sty.setName("height")))
119 {
120 height = sty.getNumberWithUnits();
121 }
122
123 if (getPres(sty.setName("viewBox")))
124 {
125 float[] coords = sty.getFloatList();
126 viewBox = new Rectangle2D.Float(coords[0], coords[1], coords[2], coords[3]);
127 }
128
129 if (getPres(sty.setName("preserveAspectRatio")))
130 {
131 String preserve = sty.getStringValue();
132
133 if (contains(preserve, "none")) { parAlignX = PA_X_NONE; parAlignY = PA_Y_NONE; }
134 else if (contains(preserve, "xMinYMin")) { parAlignX = PA_X_MIN; parAlignY = PA_Y_MIN; }
135 else if (contains(preserve, "xMidYMin")) { parAlignX = PA_X_MID; parAlignY = PA_Y_MIN; }
136 else if (contains(preserve, "xMaxYMin")) { parAlignX = PA_X_MAX; parAlignY = PA_Y_MIN; }
137 else if (contains(preserve, "xMinYMid")) { parAlignX = PA_X_MIN; parAlignY = PA_Y_MID; }
138 else if (contains(preserve, "xMidYMid")) { parAlignX = PA_X_MID; parAlignY = PA_Y_MID; }
139 else if (contains(preserve, "xMaxYMid")) { parAlignX = PA_X_MAX; parAlignY = PA_Y_MID; }
140 else if (contains(preserve, "xMinYMax")) { parAlignX = PA_X_MIN; parAlignY = PA_Y_MAX; }
141 else if (contains(preserve, "xMidYMax")) { parAlignX = PA_X_MID; parAlignY = PA_Y_MAX; }
142 else if (contains(preserve, "xMaxYMax")) { parAlignX = PA_X_MAX; parAlignY = PA_Y_MAX; }
143
144 if (contains(preserve, "meet"))
145 {
146 parSpecifier = PS_MEET;
147 }
148 else if (contains(preserve, "slice"))
149 {
150 parSpecifier = PS_SLICE;
151 }
152 }
153
154 prepareViewport();
155 }
156
157 private boolean contains(String text, String find)
158 {
159 return (text.indexOf(find) != -1);
160 }
161
162 public SVGRoot getRoot()
163 {
164 return this;
165 }
166
167 protected void prepareViewport()
168 {
169 Rectangle deviceViewport = diagram.getDeviceViewport();
170
171 Rectangle2D defaultBounds;
172 try
173 {
174 defaultBounds = getBoundingBox();
175 }
176 catch (SVGException ex)
177 {
178 defaultBounds= new Rectangle2D.Float();
179 }
180
181 //Determine destination rectangle
182 float xx, yy, ww, hh;
183 if (width != null)
184 {
185 xx = (x == null) ? 0 : StyleAttribute.convertUnitsToPixels(x.getUnits(), x.getValue());
186 if (width.getUnits() == NumberWithUnits.UT_PERCENT)
187 {
188 ww = width.getValue() * deviceViewport.width;
189 }
190 else
191 {
192 ww = StyleAttribute.convertUnitsToPixels(width.getUnits(), width.getValue());
193 }
194 }
195 else if (viewBox != null)
196 {
197 xx = (float)viewBox.x;
198 ww = (float)viewBox.width;
199 width = new NumberWithUnits(ww, NumberWithUnits.UT_PX);
200 x = new NumberWithUnits(xx, NumberWithUnits.UT_PX);
201 }
202 else
203 {
204 //Estimate size from scene bounding box
205 xx = (float)defaultBounds.getX();
206 ww = (float)defaultBounds.getWidth();
207 width = new NumberWithUnits(ww, NumberWithUnits.UT_PX);
208 x = new NumberWithUnits(xx, NumberWithUnits.UT_PX);
209 }
210
211 if (height != null)
212 {
213 yy = (y == null) ? 0 : StyleAttribute.convertUnitsToPixels(y.getUnits(), y.getValue());
214 if (height.getUnits() == NumberWithUnits.UT_PERCENT)
215 {
216 hh = height.getValue() * deviceViewport.height;
217 }
218 else
219 {
220 hh = StyleAttribute.convertUnitsToPixels(height.getUnits(), height.getValue());
221 }
222 }
223 else if (viewBox != null)
224 {
225 yy = (float)viewBox.y;
226 hh = (float)viewBox.height;
227 height = new NumberWithUnits(hh, NumberWithUnits.UT_PX);
228 y = new NumberWithUnits(yy, NumberWithUnits.UT_PX);
229 }
230 else
231 {
232 //Estimate size from scene bounding box
233 yy = (float)defaultBounds.getY();
234 hh = (float)defaultBounds.getHeight();
235 height = new NumberWithUnits(hh, NumberWithUnits.UT_PX);
236 y = new NumberWithUnits(yy, NumberWithUnits.UT_PX);
237 }
238
239 clipRect.setRect(xx, yy, ww, hh);
240
241 if (viewBox == null)
242 {
243 viewXform.setToIdentity();
244 }
245 else
246 {
247 viewXform.setToTranslation(clipRect.x, clipRect.y);
248 viewXform.scale(clipRect.width, clipRect.height);
249 viewXform.scale(1 / viewBox.width, 1 / viewBox.height);
250 viewXform.translate(-viewBox.x, -viewBox.y);
251 }
252 }
253
254 public void render(Graphics2D g) throws SVGException
255 {
256 prepareViewport();
257
258 AffineTransform cachedXform = g.getTransform();
259 g.transform(viewXform);
260
261 super.render(g);
262
263 g.setTransform(cachedXform);
264 }
265
266 public Shape getShape()
267 {
268 Shape shape = super.getShape();
269 return viewXform.createTransformedShape(shape);
270 }
271
272 public Rectangle2D getBoundingBox() throws SVGException
273 {
274 Rectangle2D bbox = super.getBoundingBox();
275 return viewXform.createTransformedShape(bbox).getBounds2D();
276 }
277
278 public float getDeviceWidth()
279 {
280 return clipRect.width;
281 }
282
283 public float getDeviceHeight()
284 {
285 return clipRect.height;
286 }
287
288 public Rectangle2D getDeviceRect(Rectangle2D rect)
289 {
290 rect.setRect(clipRect);
291 return rect;
292 }
293
294 /**
295 * Updates all attributes in this diagram associated with a time event.
296 * Ie, all attributes with track information.
297 * @return - true if this node has changed state as a result of the time
298 * update
299 */
300 public boolean updateTime(double curTime) throws SVGException
301 {
302 boolean changeState = super.updateTime(curTime);
303
304 StyleAttribute sty = new StyleAttribute();
305 boolean shapeChange = false;
306
307 if (getPres(sty.setName("x")))
308 {
309 NumberWithUnits newVal = sty.getNumberWithUnits();
310 if (!newVal.equals(x))
311 {
312 x = newVal;
313 shapeChange = true;
314 }
315 }
316
317 if (getPres(sty.setName("y")))
318 {
319 NumberWithUnits newVal = sty.getNumberWithUnits();
320 if (!newVal.equals(y))
321 {
322 y = newVal;
323 shapeChange = true;
324 }
325 }
326
327 if (getPres(sty.setName("width")))
328 {
329 NumberWithUnits newVal = sty.getNumberWithUnits();
330 if (!newVal.equals(width))
331 {
332 width = newVal;
333 shapeChange = true;
334 }
335 }
336
337 if (getPres(sty.setName("height")))
338 {
339 NumberWithUnits newVal = sty.getNumberWithUnits();
340 if (!newVal.equals(height))
341 {
342 height = newVal;
343 shapeChange = true;
344 }
345 }
346
347 if (getPres(sty.setName("viewBox")))
348 {
349 float[] coords = sty.getFloatList();
350 Rectangle2D.Float newViewBox = new Rectangle2D.Float(coords[0], coords[1], coords[2], coords[3]);
351 if (!newViewBox.equals(viewBox))
352 {
353 viewBox = newViewBox;
354 shapeChange = true;
355 }
356 }
357
358 if (shapeChange)
359 {
360 build();
361 }
362
363 return changeState || shapeChange;
364 }
365
366 /**
367 * @return the styleSheet
368 */
369 public StyleSheet getStyleSheet()
370 {
371 if (styleSheet == null)
372 {
373 for (int i = 0; i < getNumChildren(); ++i)
374 {
375 SVGElement ele = getChild(i);
376 if (ele instanceof Style)
377 {
378 return ((Style)ele).getStyleSheet();
379 }
380 }
381 }
382
383 return styleSheet;
384 }
385
386 /**
387 * @param styleSheet the styleSheet to set
388 */
389 public void setStyleSheet(StyleSheet styleSheet)
390 {
391 this.styleSheet = styleSheet;
392 }
393
394}
Note: See TracBrowser for help on using the repository browser.