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

Last change on this file since 8084 was 8084, checked in by bastiK, 9 years ago

add svn:eol-style=native for svgsalamander

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