source: josm/trunk/src/com/kitfox/svg/app/beans/SVGIcon.java@ 10787

Last change on this file since 10787 was 10787, checked in by Don-vip, 8 years ago

fix #13291 - upgrade to svgSalamander v1.1.0 (patched)

now detects two invalid SVG files: presets/sport/volleyball.svg and presets/shop/diy_store.svg

  • Property svn:eol-style set to native
File size: 14.8 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 April 21, 2005, 10:45 AM
35 */
36
37package com.kitfox.svg.app.beans;
38
39import com.kitfox.svg.SVGCache;
40import com.kitfox.svg.SVGDiagram;
41import com.kitfox.svg.SVGException;
42import com.kitfox.svg.SVGUniverse;
43import java.awt.Component;
44import java.awt.Dimension;
45import java.awt.Graphics;
46import java.awt.Graphics2D;
47import java.awt.Image;
48import java.awt.Rectangle;
49import java.awt.RenderingHints;
50import java.awt.geom.AffineTransform;
51import java.awt.geom.Rectangle2D;
52import java.awt.image.BufferedImage;
53import java.beans.PropertyChangeListener;
54import java.beans.PropertyChangeSupport;
55import java.net.URI;
56import javax.swing.ImageIcon;
57
58
59/**
60 *
61 * @author kitfox
62 */
63public class SVGIcon extends ImageIcon
64{
65 public static final long serialVersionUID = 1;
66
67 public static final String PROP_AUTOSIZE = "PROP_AUTOSIZE";
68
69 private final PropertyChangeSupport changes = new PropertyChangeSupport(this);
70
71 SVGUniverse svgUniverse = SVGCache.getSVGUniverse();
72 public static final int INTERP_NEAREST_NEIGHBOR = 0;
73 public static final int INTERP_BILINEAR = 1;
74 public static final int INTERP_BICUBIC = 2;
75
76 private boolean antiAlias;
77 private int interpolation = INTERP_NEAREST_NEIGHBOR;
78 private boolean clipToViewbox;
79
80 URI svgURI;
81
82// private boolean scaleToFit;
83 AffineTransform scaleXform = new AffineTransform();
84
85 public static final int AUTOSIZE_NONE = 0;
86 public static final int AUTOSIZE_HORIZ = 1;
87 public static final int AUTOSIZE_VERT = 2;
88 public static final int AUTOSIZE_BESTFIT = 3;
89 public static final int AUTOSIZE_STRETCH = 4;
90 private int autosize = AUTOSIZE_NONE;
91
92 Dimension preferredSize;
93
94 /** Creates a new instance of SVGIcon */
95 public SVGIcon()
96 {
97 }
98
99 public void addPropertyChangeListener(PropertyChangeListener p)
100 {
101 changes.addPropertyChangeListener(p);
102 }
103
104 public void removePropertyChangeListener(PropertyChangeListener p)
105 {
106 changes.removePropertyChangeListener(p);
107 }
108
109 public Image getImage()
110 {
111 BufferedImage bi = new BufferedImage(getIconWidth(), getIconHeight(), BufferedImage.TYPE_INT_ARGB);
112 paintIcon(null, bi.getGraphics(), 0, 0);
113 return bi;
114 }
115
116 /**
117 * @return height of this icon
118 */
119 public int getIconHeight()
120 {
121 if (preferredSize != null &&
122 (autosize == AUTOSIZE_VERT || autosize == AUTOSIZE_STRETCH
123 || autosize == AUTOSIZE_BESTFIT))
124 {
125 return preferredSize.height;
126 }
127
128 SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
129 if (diagram == null)
130 {
131 return 0;
132 }
133 return (int)diagram.getHeight();
134 }
135
136 /**
137 * @return width of this icon
138 */
139 public int getIconWidth()
140 {
141 if (preferredSize != null &&
142 (autosize == AUTOSIZE_HORIZ || autosize == AUTOSIZE_STRETCH
143 || autosize == AUTOSIZE_BESTFIT))
144 {
145 return preferredSize.width;
146 }
147
148 SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
149 if (diagram == null)
150 {
151 return 0;
152 }
153 return (int)diagram.getWidth();
154 }
155
156 /**
157 * Draws the icon to the specified component.
158 * @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
159 * @param gg - Graphics context to render SVG content to
160 * @param x - X coordinate to draw icon
161 * @param y - Y coordinate to draw icon
162 */
163 public void paintIcon(Component comp, Graphics gg, int x, int y)
164 {
165 //Copy graphics object so that
166 Graphics2D g = (Graphics2D)gg.create();
167 paintIcon(comp, g, x, y);
168 g.dispose();
169 }
170
171 private void paintIcon(Component comp, Graphics2D g, int x, int y)
172 {
173 Object oldAliasHint = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
174 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
175
176 Object oldInterpolationHint = g.getRenderingHint(RenderingHints.KEY_INTERPOLATION);
177 switch (interpolation)
178 {
179 case INTERP_NEAREST_NEIGHBOR:
180 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
181 break;
182 case INTERP_BILINEAR:
183 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
184 break;
185 case INTERP_BICUBIC:
186 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
187 break;
188 }
189
190
191 SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
192 if (diagram == null)
193 {
194 return;
195 }
196
197 g.translate(x, y);
198 diagram.setIgnoringClipHeuristic(!clipToViewbox);
199 if (clipToViewbox)
200 {
201 g.setClip(new Rectangle2D.Float(0, 0, diagram.getWidth(), diagram.getHeight()));
202 }
203
204
205 if (autosize == AUTOSIZE_NONE)
206 {
207 try
208 {
209 diagram.render(g);
210 g.translate(-x, -y);
211 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAliasHint);
212 }
213 catch (Exception e)
214 {
215 throw new RuntimeException(e);
216 }
217 return;
218 }
219
220 final int width = getIconWidth();
221 final int height = getIconHeight();
222// int width = getWidth();
223// int height = getHeight();
224
225 if (width == 0 || height == 0)
226 {
227 return;
228 }
229
230// if (width == 0 || height == 0)
231// {
232// //Chances are we're rendering offscreen
233// Dimension dim = getSize();
234// width = dim.width;
235// height = dim.height;
236// return;
237// }
238
239// g.setClip(0, 0, width, height);
240
241
242// final Rectangle2D.Double rect = new Rectangle2D.Double();
243// diagram.getViewRect(rect);
244//
245// scaleXform.setToScale(width / rect.width, height / rect.height);
246 double diaWidth = diagram.getWidth();
247 double diaHeight = diagram.getHeight();
248
249 double scaleW = 1;
250 double scaleH = 1;
251 if (autosize == AUTOSIZE_BESTFIT)
252 {
253 scaleW = scaleH = (height / diaHeight < width / diaWidth)
254 ? height / diaHeight : width / diaWidth;
255 }
256 else if (autosize == AUTOSIZE_HORIZ)
257 {
258 scaleW = scaleH = width / diaWidth;
259 }
260 else if (autosize == AUTOSIZE_VERT)
261 {
262 scaleW = scaleH = height / diaHeight;
263 }
264 else if (autosize == AUTOSIZE_STRETCH)
265 {
266 scaleW = width / diaWidth;
267 scaleH = height / diaHeight;
268 }
269 scaleXform.setToScale(scaleW, scaleH);
270
271 AffineTransform oldXform = g.getTransform();
272 g.transform(scaleXform);
273
274 try
275 {
276 diagram.render(g);
277 }
278 catch (SVGException e)
279 {
280 throw new RuntimeException(e);
281 }
282
283 g.setTransform(oldXform);
284
285
286 g.translate(-x, -y);
287
288 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAliasHint);
289 if (oldInterpolationHint != null)
290 {
291 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, oldInterpolationHint);
292 }
293 }
294
295 /**
296 * @return the universe this icon draws it's SVGDiagrams from
297 */
298 public SVGUniverse getSvgUniverse()
299 {
300 return svgUniverse;
301 }
302
303 public void setSvgUniverse(SVGUniverse svgUniverse)
304 {
305 SVGUniverse old = this.svgUniverse;
306 this.svgUniverse = svgUniverse;
307 changes.firePropertyChange("svgUniverse", old, svgUniverse);
308 }
309
310 /**
311 * @return the uni of the document being displayed by this icon
312 */
313 public URI getSvgURI()
314 {
315 return svgURI;
316 }
317
318 /**
319 * Loads an SVG document from a URI.
320 * @param svgURI - URI to load document from
321 */
322 public void setSvgURI(URI svgURI)
323 {
324 URI old = this.svgURI;
325 this.svgURI = svgURI;
326
327 SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
328 if (diagram != null)
329 {
330 Dimension size = getPreferredSize();
331 if (size == null)
332 {
333 size = new Dimension((int)diagram.getRoot().getDeviceWidth(), (int)diagram.getRoot().getDeviceHeight());
334 }
335 diagram.setDeviceViewport(new Rectangle(0, 0, size.width, size.height));
336 }
337
338 changes.firePropertyChange("svgURI", old, svgURI);
339 }
340
341 /**
342 * Loads an SVG document from the classpath. This function is equivilant to
343 * setSvgURI(new URI(getClass().getResource(resourcePath).toString());
344 * @param resourcePath - resource to load
345 */
346 public void setSvgResourcePath(String resourcePath)
347 {
348 URI old = this.svgURI;
349
350 try
351 {
352 svgURI = new URI(getClass().getResource(resourcePath).toString());
353 changes.firePropertyChange("svgURI", old, svgURI);
354
355 SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
356 if (diagram != null)
357 {
358 diagram.setDeviceViewport(new Rectangle(0, 0, preferredSize.width, preferredSize.height));
359 }
360
361 }
362 catch (Exception e)
363 {
364 svgURI = old;
365 }
366 }
367
368 /**
369 * If this SVG document has a viewbox, if scaleToFit is set, will scale the viewbox to match the
370 * preferred size of this icon
371 * @deprecated
372 * @return
373 */
374 public boolean isScaleToFit()
375 {
376 return autosize == AUTOSIZE_STRETCH;
377 }
378
379 /**
380 * @deprecated
381 * @return
382 */
383 public void setScaleToFit(boolean scaleToFit)
384 {
385 setAutosize(AUTOSIZE_STRETCH);
386// boolean old = this.scaleToFit;
387// this.scaleToFit = scaleToFit;
388// firePropertyChange("scaleToFit", old, scaleToFit);
389 }
390
391 public Dimension getPreferredSize()
392 {
393 if (preferredSize == null)
394 {
395 SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
396 if (diagram != null)
397 {
398 //preferredSize = new Dimension((int)diagram.getWidth(), (int)diagram.getHeight());
399 setPreferredSize(new Dimension((int)diagram.getWidth(), (int)diagram.getHeight()));
400 }
401 }
402
403 return new Dimension(preferredSize);
404 }
405
406 public void setPreferredSize(Dimension preferredSize)
407 {
408 Dimension old = this.preferredSize;
409 this.preferredSize = preferredSize;
410
411 SVGDiagram diagram = svgUniverse.getDiagram(svgURI);
412 if (diagram != null)
413 {
414 diagram.setDeviceViewport(new Rectangle(0, 0, preferredSize.width, preferredSize.height));
415 }
416
417 changes.firePropertyChange("preferredSize", old, preferredSize);
418 }
419
420
421 /**
422 * @return true if antiAliasing is turned on.
423 * @deprecated
424 */
425 public boolean getUseAntiAlias()
426 {
427 return getAntiAlias();
428 }
429
430 /**
431 * @param antiAlias true to use antiAliasing.
432 * @deprecated
433 */
434 public void setUseAntiAlias(boolean antiAlias)
435 {
436 setAntiAlias(antiAlias);
437 }
438
439 /**
440 * @return true if antiAliasing is turned on.
441 */
442 public boolean getAntiAlias()
443 {
444 return antiAlias;
445 }
446
447 /**
448 * @param antiAlias true to use antiAliasing.
449 */
450 public void setAntiAlias(boolean antiAlias)
451 {
452 boolean old = this.antiAlias;
453 this.antiAlias = antiAlias;
454 changes.firePropertyChange("antiAlias", old, antiAlias);
455 }
456
457 /**
458 * @return interpolation used in rescaling images
459 */
460 public int getInterpolation()
461 {
462 return interpolation;
463 }
464
465 /**
466 * @param interpolation Interpolation value used in rescaling images.
467 * Should be one of
468 * INTERP_NEAREST_NEIGHBOR - Fastest, one pixel resampling, poor quality
469 * INTERP_BILINEAR - four pixel resampling
470 * INTERP_BICUBIC - Slowest, nine pixel resampling, best quality
471 */
472 public void setInterpolation(int interpolation)
473 {
474 int old = this.interpolation;
475 this.interpolation = interpolation;
476 changes.firePropertyChange("interpolation", old, interpolation);
477 }
478
479 /**
480 * clipToViewbox will set a clip box equivilant to the SVG's viewbox before
481 * rendering.
482 */
483 public boolean isClipToViewbox()
484 {
485 return clipToViewbox;
486 }
487
488 public void setClipToViewbox(boolean clipToViewbox)
489 {
490 this.clipToViewbox = clipToViewbox;
491 }
492
493 /**
494 * @return the autosize
495 */
496 public int getAutosize()
497 {
498 return autosize;
499 }
500
501 /**
502 * @param autosize the autosize to set
503 */
504 public void setAutosize(int autosize)
505 {
506 int oldAutosize = this.autosize;
507 this.autosize = autosize;
508 changes.firePropertyChange(PROP_AUTOSIZE, oldAutosize, autosize);
509 }
510
511}
Note: See TracBrowser for help on using the repository browser.