001 /*
002 * Font.java
003 *
004 *
005 * The Salamander Project - 2D and 3D graphics libraries in Java
006 * Copyright (C) 2004 Mark McKay
007 *
008 * This library is free software; you can redistribute it and/or
009 * modify it under the terms of the GNU Lesser General Public
010 * License as published by the Free Software Foundation; either
011 * version 2.1 of the License, or (at your option) any later version.
012 *
013 * This library is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016 * Lesser General Public License for more details.
017 *
018 * You should have received a copy of the GNU Lesser General Public
019 * License along with this library; if not, write to the Free Software
020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021 *
022 * Mark McKay can be contacted at mark@kitfox.com. Salamander and other
023 * projects can be found at http://www.kitfox.com
024 *
025 * Created on February 20, 2004, 10:00 PM
026 */
027
028 package com.kitfox.svg;
029
030 import com.kitfox.svg.app.data.Handler;
031 import com.kitfox.svg.xml.*;
032
033 import java.awt.*;
034 import java.awt.geom.*;
035 import java.awt.image.*;
036 import java.net.*;
037 import java.util.List;
038
039 /**
040 * Implements an embedded font.
041 *
042 * SVG specification: http://www.w3.org/TR/SVG/fonts.html
043 *
044 * @author Mark McKay
045 * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
046 */
047 public class ImageSVG extends RenderableElement
048 {
049 float x = 0f;
050 float y = 0f;
051 float width = 0f;
052 float height = 0f;
053
054 // BufferedImage href = null;
055 URL imageSrc = null;
056
057 AffineTransform xform;
058 Rectangle2D bounds;
059
060 /** Creates a new instance of Font */
061 public ImageSVG()
062 {
063 }
064
065 protected void build() throws SVGException
066 {
067 super.build();
068
069 StyleAttribute sty = new StyleAttribute();
070
071 if (getPres(sty.setName("x"))) x = sty.getFloatValueWithUnits();
072
073 if (getPres(sty.setName("y"))) y = sty.getFloatValueWithUnits();
074
075 if (getPres(sty.setName("width"))) width = sty.getFloatValueWithUnits();
076
077 if (getPres(sty.setName("height"))) height = sty.getFloatValueWithUnits();
078
079 try {
080 if (getPres(sty.setName("xlink:href")))
081 {
082 URI src = sty.getURIValue(getXMLBase());
083 if ("data".equals(src.getScheme()))
084 {
085 imageSrc = new URL(null, src.toASCIIString(), new Handler());
086 }
087 else
088 {
089 try {
090 imageSrc = src.toURL();
091 }
092 catch (Exception e)
093 {
094 e.printStackTrace();
095 imageSrc = null;
096 }
097 }
098 }
099 }
100 catch (Exception e)
101 {
102 throw new SVGException(e);
103 }
104
105 diagram.getUniverse().registerImage(imageSrc);
106
107 //Set widths if not set
108 BufferedImage img = diagram.getUniverse().getImage(imageSrc);
109 if (img == null)
110 {
111 xform = new AffineTransform();
112 bounds = new Rectangle2D.Float();
113 return;
114 }
115
116 if (width == 0) width = img.getWidth();
117 if (height == 0) height = img.getHeight();
118
119 //Determine image xform
120 xform = new AffineTransform();
121 // xform.setToScale(this.width / img.getWidth(), this.height / img.getHeight());
122 // xform.translate(this.x, this.y);
123 xform.translate(this.x, this.y);
124 xform.scale(this.width / img.getWidth(), this.height / img.getHeight());
125
126 bounds = new Rectangle2D.Float(this.x, this.y, this.width, this.height);
127 }
128
129
130
131 public float getX() { return x; }
132 public float getY() { return y; }
133 public float getWidth() { return width; }
134 public float getHeight() { return height; }
135
136 void pick(Point2D point, boolean boundingBox, List retVec) throws SVGException
137 {
138 if (getBoundingBox().contains(point))
139 {
140 retVec.add(getPath(null));
141 }
142 }
143
144 void pick(Rectangle2D pickArea, AffineTransform ltw, boolean boundingBox, List retVec) throws SVGException
145 {
146 if (ltw.createTransformedShape(getBoundingBox()).intersects(pickArea))
147 {
148 retVec.add(getPath(null));
149 }
150 }
151
152 public void render(Graphics2D g) throws SVGException
153 {
154 StyleAttribute styleAttrib = new StyleAttribute();
155 if (getStyle(styleAttrib.setName("visibility")))
156 {
157 if (!styleAttrib.getStringValue().equals("visible")) return;
158 }
159
160 beginLayer(g);
161
162 float opacity = 1f;
163 if (getStyle(styleAttrib.setName("opacity")))
164 {
165 opacity = styleAttrib.getRatioValue();
166 }
167
168 if (opacity <= 0) return;
169
170 Composite oldComp = null;
171
172 if (opacity < 1)
173 {
174 oldComp = g.getComposite();
175 Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity);
176 g.setComposite(comp);
177 }
178
179 BufferedImage img = diagram.getUniverse().getImage(imageSrc);
180 if (img == null) return;
181
182 AffineTransform curXform = g.getTransform();
183 g.transform(xform);
184
185 g.drawImage(img, 0, 0, null);
186
187 g.setTransform(curXform);
188 if (oldComp != null) g.setComposite(oldComp);
189
190 finishLayer(g);
191 }
192
193 public Rectangle2D getBoundingBox()
194 {
195 return boundsToParent(bounds);
196 }
197
198 /**
199 * Updates all attributes in this diagram associated with a time event.
200 * Ie, all attributes with track information.
201 * @return - true if this node has changed state as a result of the time
202 * update
203 */
204 public boolean updateTime(double curTime) throws SVGException
205 {
206 // if (trackManager.getNumTracks() == 0) return false;
207 boolean changeState = super.updateTime(curTime);
208
209 //Get current values for parameters
210 StyleAttribute sty = new StyleAttribute();
211 boolean shapeChange = false;
212
213 if (getPres(sty.setName("x")))
214 {
215 float newVal = sty.getFloatValueWithUnits();
216 if (newVal != x)
217 {
218 x = newVal;
219 shapeChange = true;
220 }
221 }
222
223 if (getPres(sty.setName("y")))
224 {
225 float newVal = sty.getFloatValueWithUnits();
226 if (newVal != y)
227 {
228 y = newVal;
229 shapeChange = true;
230 }
231 }
232
233 if (getPres(sty.setName("width")))
234 {
235 float newVal = sty.getFloatValueWithUnits();
236 if (newVal != width)
237 {
238 width = newVal;
239 shapeChange = true;
240 }
241 }
242
243 if (getPres(sty.setName("height")))
244 {
245 float newVal = sty.getFloatValueWithUnits();
246 if (newVal != height)
247 {
248 height = newVal;
249 shapeChange = true;
250 }
251 }
252
253 try {
254 if (getPres(sty.setName("xlink:href")))
255 {
256 URI src = sty.getURIValue(getXMLBase());
257 URL newVal = src.toURL();
258
259 if (!newVal.equals(imageSrc))
260 {
261 imageSrc = newVal;
262 shapeChange = true;
263 }
264 }
265 }
266 catch (IllegalArgumentException ie)
267 {
268 new Exception("Image provided with illegal value for href: \"" + sty.getStringValue() + '"', ie).printStackTrace();
269 }
270 catch (Exception e)
271 {
272 e.printStackTrace();
273 }
274
275
276 if (shapeChange)
277 {
278 build();
279 // diagram.getUniverse().registerImage(imageSrc);
280 //
281 // //Set widths if not set
282 // BufferedImage img = diagram.getUniverse().getImage(imageSrc);
283 // if (img == null)
284 // {
285 // xform = new AffineTransform();
286 // bounds = new Rectangle2D.Float();
287 // }
288 // else
289 // {
290 // if (width == 0) width = img.getWidth();
291 // if (height == 0) height = img.getHeight();
292 //
293 // //Determine image xform
294 // xform = new AffineTransform();
295 //// xform.setToScale(this.width / img.getWidth(), this.height / img.getHeight());
296 //// xform.translate(this.x, this.y);
297 // xform.translate(this.x, this.y);
298 // xform.scale(this.width / img.getWidth(), this.height / img.getHeight());
299 //
300 // bounds = new Rectangle2D.Float(this.x, this.y, this.width, this.height);
301 // }
302 //
303 // return true;
304 }
305
306 return changeState || shapeChange;
307 }
308 }