source: josm/trunk/src/com/kitfox/svg/PatternSVG.java@ 4256

Last change on this file since 4256 was 4256, checked in by bastiK, 14 years ago

see #6560 - basic svg support, includes kitfox svgsalamander, r 98, patched

File size: 10.2 KB
Line 
1/*
2 * Gradient.java
3 *
4 *
5 * The Salamander Project - 2D and 3D graphics libraries in Java
6 * Copyright (C) 2004 Mark McKay
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * Mark McKay can be contacted at mark@kitfox.com. Salamander and other
23 * projects can be found at http://www.kitfox.com
24 *
25 * Created on January 26, 2004, 3:25 AM
26 */
27
28package com.kitfox.svg;
29
30import com.kitfox.svg.xml.StyleAttribute;
31import java.net.*;
32import java.util.*;
33import java.awt.geom.*;
34import java.awt.*;
35import java.awt.image.*;
36
37import com.kitfox.svg.pattern.*;
38import com.kitfox.svg.xml.*;
39import org.xml.sax.*;
40
41/**
42 * @author Mark McKay
43 * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
44 */
45public class PatternSVG extends FillElement {
46
47 public static final int GU_OBJECT_BOUNDING_BOX = 0;
48 public static final int GU_USER_SPACE_ON_USE = 1;
49
50 int gradientUnits = GU_OBJECT_BOUNDING_BOX;
51
52 float x;
53 float y;
54 float width;
55 float height;
56
57 AffineTransform patternXform = new AffineTransform();
58 Rectangle2D.Float viewBox;
59
60 Paint texPaint;
61
62 /** Creates a new instance of Gradient */
63 public PatternSVG() {
64 }
65/*
66 public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent)
67 {
68 //Load style string
69 super.loaderStartElement(helper, attrs, parent);
70
71 String href = attrs.getValue("xlink:href");
72 //If we have a link to another pattern, initialize ourselves with it's values
73 if (href != null)
74 {
75//System.err.println("Gradient.loaderStartElement() href '" + href + "'");
76 try {
77 URI src = getXMLBase().resolve(href);
78// URL url = srcUrl.toURL();
79// URL url = new URL(helper.docRoot, href);
80 PatternSVG patSrc = (PatternSVG)helper.universe.getElement(src);
81
82 gradientUnits = patSrc.gradientUnits;
83 x = patSrc.x;
84 y = patSrc.y;
85 width = patSrc.width;
86 height = patSrc.height;
87 viewBox = patSrc.viewBox;
88 patternXform.setTransform(patSrc.patternXform);
89 members.addAll(patSrc.members);
90 }
91 catch (Exception e)
92 {
93 e.printStackTrace();
94 }
95 }
96
97
98 String gradientUnits = attrs.getValue("gradientUnits");
99
100 if (gradientUnits != null)
101 {
102 if (gradientUnits.toLowerCase().equals("userspaceonuse")) this.gradientUnits = GU_USER_SPACE_ON_USE;
103 else this.gradientUnits = GU_OBJECT_BOUNDING_BOX;
104 }
105
106 String patternTransform = attrs.getValue("patternTransform");
107 if (patternTransform != null)
108 {
109 patternXform = parseTransform(patternTransform);
110 }
111
112 String x = attrs.getValue("x");
113 String y = attrs.getValue("y");
114 String width = attrs.getValue("width");
115 String height = attrs.getValue("height");
116
117 if (x != null) this.x = XMLParseUtil.parseFloat(x);
118 if (y != null) this.y = XMLParseUtil.parseFloat(y);
119 if (width != null) this.width = XMLParseUtil.parseFloat(width);
120 if (height != null) this.height = XMLParseUtil.parseFloat(height);
121
122 String viewBoxStrn = attrs.getValue("viewBox");
123 if (viewBoxStrn != null)
124 {
125 float[] dim = XMLParseUtil.parseFloatList(viewBoxStrn);
126 viewBox = new Rectangle2D.Float(dim[0], dim[1], dim[2], dim[3]);
127 }
128 }
129 */
130 /**
131 * Called after the start element but before the end element to indicate
132 * each child tag that has been processed
133 */
134 public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
135 {
136 super.loaderAddChild(helper, child);
137
138// members.add(child);
139 }
140
141 protected void build() throws SVGException
142 {
143 super.build();
144
145 StyleAttribute sty = new StyleAttribute();
146
147 //Load style string
148 String href = null;
149 if (getPres(sty.setName("xlink:href"))) href = sty.getStringValue();
150 //String href = attrs.getValue("xlink:href");
151 //If we have a link to another pattern, initialize ourselves with it's values
152 if (href != null)
153 {
154//System.err.println("Gradient.loaderStartElement() href '" + href + "'");
155 try {
156 URI src = getXMLBase().resolve(href);
157 PatternSVG patSrc = (PatternSVG)diagram.getUniverse().getElement(src);
158
159 gradientUnits = patSrc.gradientUnits;
160 x = patSrc.x;
161 y = patSrc.y;
162 width = patSrc.width;
163 height = patSrc.height;
164 viewBox = patSrc.viewBox;
165 patternXform.setTransform(patSrc.patternXform);
166 children.addAll(patSrc.children);
167 }
168 catch (Exception e)
169 {
170 e.printStackTrace();
171 }
172 }
173
174 String gradientUnits = "";
175 if (getPres(sty.setName("gradientUnits"))) gradientUnits = sty.getStringValue().toLowerCase();
176 if (gradientUnits.equals("userspaceonuse")) this.gradientUnits = GU_USER_SPACE_ON_USE;
177 else this.gradientUnits = GU_OBJECT_BOUNDING_BOX;
178
179 String patternTransform = "";
180 if (getPres(sty.setName("patternTransform"))) patternTransform = sty.getStringValue();
181 patternXform = parseTransform(patternTransform);
182
183
184 if (getPres(sty.setName("x"))) x = sty.getFloatValueWithUnits();
185
186 if (getPres(sty.setName("y"))) y = sty.getFloatValueWithUnits();
187
188 if (getPres(sty.setName("width"))) width = sty.getFloatValueWithUnits();
189
190 if (getPres(sty.setName("height"))) height = sty.getFloatValueWithUnits();
191
192 if (getPres(sty.setName("viewBox")))
193 {
194 float[] dim = sty.getFloatList();
195 viewBox = new Rectangle2D.Float(dim[0], dim[1], dim[2], dim[3]);
196 }
197
198 preparePattern();
199 }
200
201/*
202 public void loaderEndElement(SVGLoaderHelper helper)
203 {
204 build();
205 }
206 */
207
208 protected void preparePattern() throws SVGException
209 {
210 //For now, treat all fills as UserSpaceOnUse. Otherwise, we'll need
211 // a different paint for every object.
212 int tileWidth = (int)width;
213 int tileHeight = (int)height;
214
215 float stretchX = 1f, stretchY = 1f;
216 if (!patternXform.isIdentity())
217 {
218 //Scale our source tile so that we can have nice sampling from it.
219 float xlateX = (float)patternXform.getTranslateX();
220 float xlateY = (float)patternXform.getTranslateY();
221
222 Point2D.Float pt = new Point2D.Float(), pt2 = new Point2D.Float();
223
224 pt.setLocation(width, 0);
225 patternXform.transform(pt, pt2);
226 pt2.x -= xlateX;
227 pt2.y -= xlateY;
228 stretchX = (float)Math.sqrt(pt2.x * pt2.x + pt2.y * pt2.y) * 1.5f / width;
229
230 pt.setLocation(height, 0);
231 patternXform.transform(pt, pt2);
232 pt2.x -= xlateX;
233 pt2.y -= xlateY;
234 stretchY = (float)Math.sqrt(pt2.x * pt2.x + pt2.y * pt2.y) * 1.5f / height;
235
236 tileWidth *= stretchX;
237 tileHeight *= stretchY;
238 }
239
240 if (tileWidth == 0 || tileHeight == 0)
241 {
242 //Use defaults if tile has degenerate size
243 return;
244 }
245
246 BufferedImage buf = new BufferedImage(tileWidth, tileHeight, BufferedImage.TYPE_INT_ARGB);
247 Graphics2D g = buf.createGraphics();
248 g.setClip(0, 0, tileWidth, tileHeight);
249 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
250
251 for (Iterator it = children.iterator(); it.hasNext();)
252 {
253 SVGElement ele = (SVGElement)it.next();
254 if (ele instanceof RenderableElement)
255 {
256 AffineTransform xform = new AffineTransform();
257
258 if (viewBox == null)
259 {
260 xform.translate(-x, -y);
261 }
262 else
263 {
264 xform.scale(tileWidth / viewBox.width, tileHeight / viewBox.height);
265 xform.translate(-viewBox.x, -viewBox.y);
266 }
267
268 g.setTransform(xform);
269 ((RenderableElement)ele).render(g);
270 }
271 }
272
273 g.dispose();
274
275//try {
276//javax.imageio.ImageIO.write(buf, "png", new java.io.File("c:\\tmp\\texPaint.png"));
277//} catch (Exception e ) {}
278
279 if (patternXform.isIdentity())
280 {
281 texPaint = new TexturePaint(buf, new Rectangle2D.Float(x, y, width, height));
282 }
283 else
284 {
285 patternXform.scale(1 / stretchX, 1 / stretchY);
286 texPaint = new PatternPaint(buf, patternXform);
287 }
288 }
289
290 public Paint getPaint(Rectangle2D bounds, AffineTransform xform)
291 {
292 return texPaint;
293 }
294
295 /**
296 * Updates all attributes in this diagram associated with a time event.
297 * Ie, all attributes with track information.
298 * @return - true if this node has changed state as a result of the time
299 * update
300 */
301 public boolean updateTime(double curTime) throws SVGException
302 {
303 //Patterns don't change state
304 return false;
305 }
306}
Note: See TracBrowser for help on using the repository browser.