001/* 002 * SVG Salamander 003 * Copyright (c) 2004, Mark McKay 004 * All rights reserved. 005 * 006 * Redistribution and use in source and binary forms, with or 007 * without modification, are permitted provided that the following 008 * conditions are met: 009 * 010 * - Redistributions of source code must retain the above 011 * copyright notice, this list of conditions and the following 012 * disclaimer. 013 * - Redistributions in binary form must reproduce the above 014 * copyright notice, this list of conditions and the following 015 * disclaimer in the documentation and/or other materials 016 * provided with the distribution. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 019 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 020 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 021 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 022 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 023 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 025 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 026 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 027 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 029 * OF THE POSSIBILITY OF SUCH DAMAGE. 030 * 031 * Mark McKay can be contacted at mark@kitfox.com. Salamander and other 032 * projects can be found at http://www.kitfox.com 033 * 034 * Created on February 20, 2004, 10:00 PM 035 */ 036package com.kitfox.svg; 037 038import com.kitfox.svg.app.data.Handler; 039import com.kitfox.svg.xml.StyleAttribute; 040import java.awt.AlphaComposite; 041import java.awt.Composite; 042import java.awt.Graphics2D; 043import java.awt.geom.AffineTransform; 044import java.awt.geom.Point2D; 045import java.awt.geom.Rectangle2D; 046import java.awt.image.BufferedImage; 047import java.net.URI; 048import java.net.URL; 049import java.util.List; 050import java.util.logging.Level; 051import java.util.logging.Logger; 052 053/** 054 * Implements an image. 055 * 056 * @author Mark McKay 057 * @author <a href="mailto:mark@kitfox.com">Mark McKay</a> 058 */ 059public class ImageSVG extends RenderableElement 060{ 061 public static final String TAG_NAME = "image"; 062 063 float x = 0f; 064 float y = 0f; 065 float width = 0f; 066 float height = 0f; 067// BufferedImage href = null; 068 URL imageSrc = null; 069 AffineTransform xform; 070 Rectangle2D bounds; 071 072 /** 073 * Creates a new instance of Font 074 */ 075 public ImageSVG() 076 { 077 } 078 079 public String getTagName() 080 { 081 return TAG_NAME; 082 } 083 084 protected void build() throws SVGException 085 { 086 super.build(); 087 088 StyleAttribute sty = new StyleAttribute(); 089 090 if (getPres(sty.setName("x"))) 091 { 092 x = sty.getFloatValueWithUnits(); 093 } 094 095 if (getPres(sty.setName("y"))) 096 { 097 y = sty.getFloatValueWithUnits(); 098 } 099 100 if (getPres(sty.setName("width"))) 101 { 102 width = sty.getFloatValueWithUnits(); 103 } 104 105 if (getPres(sty.setName("height"))) 106 { 107 height = sty.getFloatValueWithUnits(); 108 } 109 110 try 111 { 112 if (getPres(sty.setName("xlink:href"))) 113 { 114 115 116 URI src = sty.getURIValue(getXMLBase()); 117 if ("data".equals(src.getScheme())) 118 { 119 imageSrc = new URL(null, src.toASCIIString(), new Handler()); 120 } 121 else 122 { 123 124 if (!diagram.getUniverse().isImageDataInlineOnly()) 125 { 126 try 127 { 128 imageSrc = src.toURL(); 129 } catch (Exception e) 130 { 131 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, 132 "Could not parse xlink:href " + src, e); 133 // e.printStackTrace(); 134 imageSrc = null; 135 } 136 } 137 } 138 } 139 } catch (Exception e) 140 { 141 throw new SVGException(e); 142 } 143 144 diagram.getUniverse().registerImage(imageSrc); 145 146 //Set widths if not set 147 BufferedImage img = diagram.getUniverse().getImage(imageSrc); 148 if (img == null) 149 { 150 xform = new AffineTransform(); 151 bounds = new Rectangle2D.Float(); 152 return; 153 } 154 155 if (width == 0) 156 { 157 width = img.getWidth(); 158 } 159 if (height == 0) 160 { 161 height = img.getHeight(); 162 } 163 164 //Determine image xform 165 xform = new AffineTransform(); 166// xform.setToScale(this.width / img.getWidth(), this.height / img.getHeight()); 167// xform.translate(this.x, this.y); 168 xform.translate(this.x, this.y); 169 xform.scale(this.width / img.getWidth(), this.height / img.getHeight()); 170 171 bounds = new Rectangle2D.Float(this.x, this.y, this.width, this.height); 172 } 173 174 public float getX() 175 { 176 return x; 177 } 178 179 public float getY() 180 { 181 return y; 182 } 183 184 public float getWidth() 185 { 186 return width; 187 } 188 189 public float getHeight() 190 { 191 return height; 192 } 193 194 void pick(Point2D point, boolean boundingBox, List retVec) throws SVGException 195 { 196 if (getBoundingBox().contains(point)) 197 { 198 retVec.add(getPath(null)); 199 } 200 } 201 202 void pick(Rectangle2D pickArea, AffineTransform ltw, boolean boundingBox, List retVec) throws SVGException 203 { 204 if (ltw.createTransformedShape(getBoundingBox()).intersects(pickArea)) 205 { 206 retVec.add(getPath(null)); 207 } 208 } 209 210 public void render(Graphics2D g) throws SVGException 211 { 212 StyleAttribute styleAttrib = new StyleAttribute(); 213 if (getStyle(styleAttrib.setName("visibility"))) 214 { 215 if (!styleAttrib.getStringValue().equals("visible")) 216 { 217 return; 218 } 219 } 220 221 if (getStyle(styleAttrib.setName("display"))) 222 { 223 if (styleAttrib.getStringValue().equals("none")) 224 { 225 return; 226 } 227 } 228 229 beginLayer(g); 230 231 float opacity = 1f; 232 if (getStyle(styleAttrib.setName("opacity"))) 233 { 234 opacity = styleAttrib.getRatioValue(); 235 } 236 237 if (opacity <= 0) 238 { 239 return; 240 } 241 242 Composite oldComp = null; 243 244 if (opacity < 1) 245 { 246 oldComp = g.getComposite(); 247 Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity); 248 g.setComposite(comp); 249 } 250 251 BufferedImage img = diagram.getUniverse().getImage(imageSrc); 252 if (img == null) 253 { 254 return; 255 } 256 257 AffineTransform curXform = g.getTransform(); 258 g.transform(xform); 259 260 g.drawImage(img, 0, 0, null); 261 262 g.setTransform(curXform); 263 if (oldComp != null) 264 { 265 g.setComposite(oldComp); 266 } 267 268 finishLayer(g); 269 } 270 271 public Rectangle2D getBoundingBox() 272 { 273 return boundsToParent(bounds); 274 } 275 276 /** 277 * Updates all attributes in this diagram associated with a time event. Ie, 278 * all attributes with track information. 279 * 280 * @return - true if this node has changed state as a result of the time 281 * update 282 */ 283 public boolean updateTime(double curTime) throws SVGException 284 { 285// if (trackManager.getNumTracks() == 0) return false; 286 boolean changeState = super.updateTime(curTime); 287 288 //Get current values for parameters 289 StyleAttribute sty = new StyleAttribute(); 290 boolean shapeChange = false; 291 292 if (getPres(sty.setName("x"))) 293 { 294 float newVal = sty.getFloatValueWithUnits(); 295 if (newVal != x) 296 { 297 x = newVal; 298 shapeChange = true; 299 } 300 } 301 302 if (getPres(sty.setName("y"))) 303 { 304 float newVal = sty.getFloatValueWithUnits(); 305 if (newVal != y) 306 { 307 y = newVal; 308 shapeChange = true; 309 } 310 } 311 312 if (getPres(sty.setName("width"))) 313 { 314 float newVal = sty.getFloatValueWithUnits(); 315 if (newVal != width) 316 { 317 width = newVal; 318 shapeChange = true; 319 } 320 } 321 322 if (getPres(sty.setName("height"))) 323 { 324 float newVal = sty.getFloatValueWithUnits(); 325 if (newVal != height) 326 { 327 height = newVal; 328 shapeChange = true; 329 } 330 } 331 332 try 333 { 334 if (getPres(sty.setName("xlink:href"))) 335 { 336 URI src = sty.getURIValue(getXMLBase()); 337 338 URL newVal; 339 if ("data".equals(src.getScheme())) 340 { 341 newVal = new URL(null, src.toASCIIString(), new Handler()); 342 } else 343 { 344 newVal = src.toURL(); 345 } 346 347 if (!newVal.equals(imageSrc)) 348 { 349 imageSrc = newVal; 350 shapeChange = true; 351 } 352 } 353 } catch (IllegalArgumentException ie) 354 { 355 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, 356 "Image provided with illegal value for href: \"" 357 + sty.getStringValue() + '"', ie); 358 } catch (Exception e) 359 { 360 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, 361 "Could not parse xlink:href", e); 362 } 363 364 365 if (shapeChange) 366 { 367 build(); 368// diagram.getUniverse().registerImage(imageSrc); 369// 370// //Set widths if not set 371// BufferedImage img = diagram.getUniverse().getImage(imageSrc); 372// if (img == null) 373// { 374// xform = new AffineTransform(); 375// bounds = new Rectangle2D.Float(); 376// } 377// else 378// { 379// if (width == 0) width = img.getWidth(); 380// if (height == 0) height = img.getHeight(); 381// 382// //Determine image xform 383// xform = new AffineTransform(); 384//// xform.setToScale(this.width / img.getWidth(), this.height / img.getHeight()); 385//// xform.translate(this.x, this.y); 386// xform.translate(this.x, this.y); 387// xform.scale(this.width / img.getWidth(), this.height / img.getHeight()); 388// 389// bounds = new Rectangle2D.Float(this.x, this.y, this.width, this.height); 390// } 391// 392// return true; 393 } 394 395 return changeState || shapeChange; 396 } 397}