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

Last change on this file since 6388 was 6002, checked in by Don-vip, 11 years ago

fix #8742 - update svgsalamander to release 0.1.18+patch (fix bug SVGSALAMANDER-26) -> allow to open more SVG files

File size: 9.0 KB
Line 
1/*
2 * SVG Salamander
3 * Copyright (c) 2004, Mark McKay
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or
7 * without modification, are permitted provided that the following
8 * conditions are met:
9 *
10 * - Redistributions of source code must retain the above
11 * copyright notice, this list of conditions and the following
12 * disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials
16 * provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Mark McKay can be contacted at mark@kitfox.com. Salamander and other
32 * projects can be found at http://www.kitfox.com
33 *
34 * Created on January 26, 2004, 3:25 AM
35 */
36package com.kitfox.svg;
37
38import com.kitfox.svg.pattern.PatternPaint;
39import com.kitfox.svg.xml.StyleAttribute;
40import java.awt.Graphics2D;
41import java.awt.Paint;
42import java.awt.RenderingHints;
43import java.awt.TexturePaint;
44import java.awt.geom.AffineTransform;
45import java.awt.geom.Point2D;
46import java.awt.geom.Rectangle2D;
47import java.awt.image.BufferedImage;
48import java.net.URI;
49import java.util.Iterator;
50import java.util.logging.Level;
51import java.util.logging.Logger;
52
53/**
54 * @author Mark McKay
55 * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
56 */
57public class PatternSVG extends FillElement
58{
59 public static final String TAG_NAME = "pattern";
60
61 public static final int GU_OBJECT_BOUNDING_BOX = 0;
62 public static final int GU_USER_SPACE_ON_USE = 1;
63 int gradientUnits = GU_OBJECT_BOUNDING_BOX;
64 float x;
65 float y;
66 float width;
67 float height;
68 AffineTransform patternXform = new AffineTransform();
69 Rectangle2D.Float viewBox;
70 Paint texPaint;
71
72 /**
73 * Creates a new instance of Gradient
74 */
75 public PatternSVG()
76 {
77 }
78
79 public String getTagName()
80 {
81 return TAG_NAME;
82 }
83
84 /**
85 * Called after the start element but before the end element to indicate
86 * each child tag that has been processed
87 */
88 public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
89 {
90 super.loaderAddChild(helper, child);
91 }
92
93 protected void build() throws SVGException
94 {
95 super.build();
96
97 StyleAttribute sty = new StyleAttribute();
98
99 //Load style string
100 String href = null;
101 if (getPres(sty.setName("xlink:href")))
102 {
103 href = sty.getStringValue();
104 }
105 //String href = attrs.getValue("xlink:href");
106 //If we have a link to another pattern, initialize ourselves with it's values
107 if (href != null)
108 {
109//System.err.println("Gradient.loaderStartElement() href '" + href + "'");
110 try
111 {
112 URI src = getXMLBase().resolve(href);
113 PatternSVG patSrc = (PatternSVG) diagram.getUniverse().getElement(src);
114
115 gradientUnits = patSrc.gradientUnits;
116 x = patSrc.x;
117 y = patSrc.y;
118 width = patSrc.width;
119 height = patSrc.height;
120 viewBox = patSrc.viewBox;
121 patternXform.setTransform(patSrc.patternXform);
122 children.addAll(patSrc.children);
123 } catch (Exception e)
124 {
125 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
126 "Could not parse xlink:href", e);
127 }
128 }
129
130 String gradientUnits = "";
131 if (getPres(sty.setName("gradientUnits")))
132 {
133 gradientUnits = sty.getStringValue().toLowerCase();
134 }
135 if (gradientUnits.equals("userspaceonuse"))
136 {
137 this.gradientUnits = GU_USER_SPACE_ON_USE;
138 } else
139 {
140 this.gradientUnits = GU_OBJECT_BOUNDING_BOX;
141 }
142
143 String patternTransform = "";
144 if (getPres(sty.setName("patternTransform")))
145 {
146 patternTransform = sty.getStringValue();
147 }
148 patternXform = parseTransform(patternTransform);
149
150
151 if (getPres(sty.setName("x")))
152 {
153 x = sty.getFloatValueWithUnits();
154 }
155
156 if (getPres(sty.setName("y")))
157 {
158 y = sty.getFloatValueWithUnits();
159 }
160
161 if (getPres(sty.setName("width")))
162 {
163 width = sty.getFloatValueWithUnits();
164 }
165
166 if (getPres(sty.setName("height")))
167 {
168 height = sty.getFloatValueWithUnits();
169 }
170
171 if (getPres(sty.setName("viewBox")))
172 {
173 float[] dim = sty.getFloatList();
174 viewBox = new Rectangle2D.Float(dim[0], dim[1], dim[2], dim[3]);
175 }
176
177 preparePattern();
178 }
179
180 /*
181 public void loaderEndElement(SVGLoaderHelper helper)
182 {
183 build();
184 }
185 */
186 protected void preparePattern() throws SVGException
187 {
188 //For now, treat all fills as UserSpaceOnUse. Otherwise, we'll need
189 // a different paint for every object.
190 int tileWidth = (int) width;
191 int tileHeight = (int) height;
192
193 float stretchX = 1f, stretchY = 1f;
194 if (!patternXform.isIdentity())
195 {
196 //Scale our source tile so that we can have nice sampling from it.
197 float xlateX = (float) patternXform.getTranslateX();
198 float xlateY = (float) patternXform.getTranslateY();
199
200 Point2D.Float pt = new Point2D.Float(), pt2 = new Point2D.Float();
201
202 pt.setLocation(width, 0);
203 patternXform.transform(pt, pt2);
204 pt2.x -= xlateX;
205 pt2.y -= xlateY;
206 stretchX = (float) Math.sqrt(pt2.x * pt2.x + pt2.y * pt2.y) * 1.5f / width;
207
208 pt.setLocation(height, 0);
209 patternXform.transform(pt, pt2);
210 pt2.x -= xlateX;
211 pt2.y -= xlateY;
212 stretchY = (float) Math.sqrt(pt2.x * pt2.x + pt2.y * pt2.y) * 1.5f / height;
213
214 tileWidth *= stretchX;
215 tileHeight *= stretchY;
216 }
217
218 if (tileWidth == 0 || tileHeight == 0)
219 {
220 //Use defaults if tile has degenerate size
221 return;
222 }
223
224 BufferedImage buf = new BufferedImage(tileWidth, tileHeight, BufferedImage.TYPE_INT_ARGB);
225 Graphics2D g = buf.createGraphics();
226 g.setClip(0, 0, tileWidth, tileHeight);
227 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
228
229 for (Iterator it = children.iterator(); it.hasNext();)
230 {
231 SVGElement ele = (SVGElement) it.next();
232 if (ele instanceof RenderableElement)
233 {
234 AffineTransform xform = new AffineTransform();
235
236 if (viewBox == null)
237 {
238 xform.translate(-x, -y);
239 } else
240 {
241 xform.scale(tileWidth / viewBox.width, tileHeight / viewBox.height);
242 xform.translate(-viewBox.x, -viewBox.y);
243 }
244
245 g.setTransform(xform);
246 ((RenderableElement) ele).render(g);
247 }
248 }
249
250 g.dispose();
251
252//try {
253//javax.imageio.ImageIO.write(buf, "png", new java.io.File("c:\\tmp\\texPaint.png"));
254//} catch (Exception e ) {}
255
256 if (patternXform.isIdentity())
257 {
258 texPaint = new TexturePaint(buf, new Rectangle2D.Float(x, y, width, height));
259 } else
260 {
261 patternXform.scale(1 / stretchX, 1 / stretchY);
262 texPaint = new PatternPaint(buf, patternXform);
263 }
264 }
265
266 public Paint getPaint(Rectangle2D bounds, AffineTransform xform)
267 {
268 return texPaint;
269 }
270
271 /**
272 * Updates all attributes in this diagram associated with a time event. Ie,
273 * all attributes with track information.
274 *
275 * @return - true if this node has changed state as a result of the time
276 * update
277 */
278 public boolean updateTime(double curTime) throws SVGException
279 {
280 //Patterns don't change state
281 return false;
282 }
283}
Note: See TracBrowser for help on using the repository browser.