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