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 if (getStyle(styleAttrib.setName("display"))) 215 { 216 if (styleAttrib.getStringValue().equals("none")) 217 { 218 return; 219 } 220 } 221 222 beginLayer(g); 223 224 float opacity = 1f; 225 if (getStyle(styleAttrib.setName("opacity"))) 226 { 227 opacity = styleAttrib.getRatioValue(); 228 } 229 230 if (opacity <= 0) 231 { 232 return; 233 } 234 235 Composite oldComp = null; 236 237 if (opacity < 1) 238 { 239 oldComp = g.getComposite(); 240 Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity); 241 g.setComposite(comp); 242 } 243 244 BufferedImage img = diagram.getUniverse().getImage(imageSrc); 245 if (img == null) 246 { 247 return; 248 } 249 250 AffineTransform curXform = g.getTransform(); 251 g.transform(xform); 252 253 g.drawImage(img, 0, 0, null); 254 255 g.setTransform(curXform); 256 if (oldComp != null) 257 { 258 g.setComposite(oldComp); 259 } 260 261 finishLayer(g); 262 } 263 264 public Rectangle2D getBoundingBox() 265 { 266 return boundsToParent(bounds); 267 } 268 269 /** 270 * Updates all attributes in this diagram associated with a time event. Ie, 271 * all attributes with track information. 272 * 273 * @return - true if this node has changed state as a result of the time 274 * update 275 */ 276 public boolean updateTime(double curTime) throws SVGException 277 { 278// if (trackManager.getNumTracks() == 0) return false; 279 boolean changeState = super.updateTime(curTime); 280 281 //Get current values for parameters 282 StyleAttribute sty = new StyleAttribute(); 283 boolean shapeChange = false; 284 285 if (getPres(sty.setName("x"))) 286 { 287 float newVal = sty.getFloatValueWithUnits(); 288 if (newVal != x) 289 { 290 x = newVal; 291 shapeChange = true; 292 } 293 } 294 295 if (getPres(sty.setName("y"))) 296 { 297 float newVal = sty.getFloatValueWithUnits(); 298 if (newVal != y) 299 { 300 y = newVal; 301 shapeChange = true; 302 } 303 } 304 305 if (getPres(sty.setName("width"))) 306 { 307 float newVal = sty.getFloatValueWithUnits(); 308 if (newVal != width) 309 { 310 width = newVal; 311 shapeChange = true; 312 } 313 } 314 315 if (getPres(sty.setName("height"))) 316 { 317 float newVal = sty.getFloatValueWithUnits(); 318 if (newVal != height) 319 { 320 height = newVal; 321 shapeChange = true; 322 } 323 } 324 325 try 326 { 327 if (getPres(sty.setName("xlink:href"))) 328 { 329 URI src = sty.getURIValue(getXMLBase()); 330 331 URL newVal; 332 if ("data".equals(src.getScheme())) 333 { 334 newVal = new URL(null, src.toASCIIString(), new Handler()); 335 } else 336 { 337 newVal = src.toURL(); 338 } 339 340 if (!newVal.equals(imageSrc)) 341 { 342 imageSrc = newVal; 343 shapeChange = true; 344 } 345 } 346 } catch (IllegalArgumentException ie) 347 { 348 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, 349 "Image provided with illegal value for href: \"" 350 + sty.getStringValue() + '"', ie); 351 } catch (Exception e) 352 { 353 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, 354 "Could not parse xlink:href", e); 355 } 356 357 358 if (shapeChange) 359 { 360 build(); 361// diagram.getUniverse().registerImage(imageSrc); 362// 363// //Set widths if not set 364// BufferedImage img = diagram.getUniverse().getImage(imageSrc); 365// if (img == null) 366// { 367// xform = new AffineTransform(); 368// bounds = new Rectangle2D.Float(); 369// } 370// else 371// { 372// if (width == 0) width = img.getWidth(); 373// if (height == 0) height = img.getHeight(); 374// 375// //Determine image xform 376// xform = new AffineTransform(); 377//// xform.setToScale(this.width / img.getWidth(), this.height / img.getHeight()); 378//// xform.translate(this.x, this.y); 379// xform.translate(this.x, this.y); 380// xform.scale(this.width / img.getWidth(), this.height / img.getHeight()); 381// 382// bounds = new Rectangle2D.Float(this.x, this.y, this.width, this.height); 383// } 384// 385// return true; 386 } 387 388 return changeState || shapeChange; 389 } 390}