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 URI src = sty.getURIValue(getXMLBase()); 115 if ("data".equals(src.getScheme())) 116 { 117 imageSrc = new URL(null, src.toASCIIString(), new Handler()); 118 } else 119 { 120 try 121 { 122 imageSrc = src.toURL(); 123 } catch (Exception e) 124 { 125 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, 126 "Could not parse xlink:href " + src, e); 127// e.printStackTrace(); 128 imageSrc = null; 129 } 130 } 131 } 132 } catch (Exception e) 133 { 134 throw new SVGException(e); 135 } 136 137 diagram.getUniverse().registerImage(imageSrc); 138 139 //Set widths if not set 140 BufferedImage img = diagram.getUniverse().getImage(imageSrc); 141 if (img == null) 142 { 143 xform = new AffineTransform(); 144 bounds = new Rectangle2D.Float(); 145 return; 146 } 147 148 if (width == 0) 149 { 150 width = img.getWidth(); 151 } 152 if (height == 0) 153 { 154 height = img.getHeight(); 155 } 156 157 //Determine image xform 158 xform = new AffineTransform(); 159// xform.setToScale(this.width / img.getWidth(), this.height / img.getHeight()); 160// xform.translate(this.x, this.y); 161 xform.translate(this.x, this.y); 162 xform.scale(this.width / img.getWidth(), this.height / img.getHeight()); 163 164 bounds = new Rectangle2D.Float(this.x, this.y, this.width, this.height); 165 } 166 167 public float getX() 168 { 169 return x; 170 } 171 172 public float getY() 173 { 174 return y; 175 } 176 177 public float getWidth() 178 { 179 return width; 180 } 181 182 public float getHeight() 183 { 184 return height; 185 } 186 187 void pick(Point2D point, boolean boundingBox, List retVec) throws SVGException 188 { 189 if (getBoundingBox().contains(point)) 190 { 191 retVec.add(getPath(null)); 192 } 193 } 194 195 void pick(Rectangle2D pickArea, AffineTransform ltw, boolean boundingBox, List retVec) throws SVGException 196 { 197 if (ltw.createTransformedShape(getBoundingBox()).intersects(pickArea)) 198 { 199 retVec.add(getPath(null)); 200 } 201 } 202 203 public void render(Graphics2D g) throws SVGException 204 { 205 StyleAttribute styleAttrib = new StyleAttribute(); 206 if (getStyle(styleAttrib.setName("visibility"))) 207 { 208 if (!styleAttrib.getStringValue().equals("visible")) 209 { 210 return; 211 } 212 } 213 214 beginLayer(g); 215 216 float opacity = 1f; 217 if (getStyle(styleAttrib.setName("opacity"))) 218 { 219 opacity = styleAttrib.getRatioValue(); 220 } 221 222 if (opacity <= 0) 223 { 224 return; 225 } 226 227 Composite oldComp = null; 228 229 if (opacity < 1) 230 { 231 oldComp = g.getComposite(); 232 Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity); 233 g.setComposite(comp); 234 } 235 236 BufferedImage img = diagram.getUniverse().getImage(imageSrc); 237 if (img == null) 238 { 239 return; 240 } 241 242 AffineTransform curXform = g.getTransform(); 243 g.transform(xform); 244 245 g.drawImage(img, 0, 0, null); 246 247 g.setTransform(curXform); 248 if (oldComp != null) 249 { 250 g.setComposite(oldComp); 251 } 252 253 finishLayer(g); 254 } 255 256 public Rectangle2D getBoundingBox() 257 { 258 return boundsToParent(bounds); 259 } 260 261 /** 262 * Updates all attributes in this diagram associated with a time event. Ie, 263 * all attributes with track information. 264 * 265 * @return - true if this node has changed state as a result of the time 266 * update 267 */ 268 public boolean updateTime(double curTime) throws SVGException 269 { 270// if (trackManager.getNumTracks() == 0) return false; 271 boolean changeState = super.updateTime(curTime); 272 273 //Get current values for parameters 274 StyleAttribute sty = new StyleAttribute(); 275 boolean shapeChange = false; 276 277 if (getPres(sty.setName("x"))) 278 { 279 float newVal = sty.getFloatValueWithUnits(); 280 if (newVal != x) 281 { 282 x = newVal; 283 shapeChange = true; 284 } 285 } 286 287 if (getPres(sty.setName("y"))) 288 { 289 float newVal = sty.getFloatValueWithUnits(); 290 if (newVal != y) 291 { 292 y = newVal; 293 shapeChange = true; 294 } 295 } 296 297 if (getPres(sty.setName("width"))) 298 { 299 float newVal = sty.getFloatValueWithUnits(); 300 if (newVal != width) 301 { 302 width = newVal; 303 shapeChange = true; 304 } 305 } 306 307 if (getPres(sty.setName("height"))) 308 { 309 float newVal = sty.getFloatValueWithUnits(); 310 if (newVal != height) 311 { 312 height = newVal; 313 shapeChange = true; 314 } 315 } 316 317 try 318 { 319 if (getPres(sty.setName("xlink:href"))) 320 { 321 URI src = sty.getURIValue(getXMLBase()); 322 323 URL newVal; 324 if ("data".equals(src.getScheme())) 325 { 326 newVal = new URL(null, src.toASCIIString(), new Handler()); 327 } else 328 { 329 newVal = src.toURL(); 330 } 331 332 if (!newVal.equals(imageSrc)) 333 { 334 imageSrc = newVal; 335 shapeChange = true; 336 } 337 } 338 } catch (IllegalArgumentException ie) 339 { 340 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, 341 "Image provided with illegal value for href: \"" 342 + sty.getStringValue() + '"', ie); 343 } catch (Exception e) 344 { 345 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, 346 "Could not parse xlink:href", e); 347 } 348 349 350 if (shapeChange) 351 { 352 build(); 353// diagram.getUniverse().registerImage(imageSrc); 354// 355// //Set widths if not set 356// BufferedImage img = diagram.getUniverse().getImage(imageSrc); 357// if (img == null) 358// { 359// xform = new AffineTransform(); 360// bounds = new Rectangle2D.Float(); 361// } 362// else 363// { 364// if (width == 0) width = img.getWidth(); 365// if (height == 0) height = img.getHeight(); 366// 367// //Determine image xform 368// xform = new AffineTransform(); 369//// xform.setToScale(this.width / img.getWidth(), this.height / img.getHeight()); 370//// xform.translate(this.x, this.y); 371// xform.translate(this.x, this.y); 372// xform.scale(this.width / img.getWidth(), this.height / img.getHeight()); 373// 374// bounds = new Rectangle2D.Float(this.x, this.y, this.width, this.height); 375// } 376// 377// return true; 378 } 379 380 return changeState || shapeChange; 381 } 382}