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

Last change on this file since 13376 was 11525, checked in by Don-vip, 7 years ago

see #14319 - update to latest version of svgSalamander (2017-01-07, patched)

  • Property svn:eol-style set to native
File size: 8.7 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.logging.Level;
50import java.util.logging.Logger;
51
52/**
53 * @author Mark McKay
54 * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
55 */
56public class PatternSVG extends FillElement
57{
58 public static final String TAG_NAME = "pattern";
59
60 public static final int GU_OBJECT_BOUNDING_BOX = 0;
61 public static final int GU_USER_SPACE_ON_USE = 1;
62 int gradientUnits = GU_OBJECT_BOUNDING_BOX;
63 float x;
64 float y;
65 float width;
66 float height;
67 AffineTransform patternXform = new AffineTransform();
68 Rectangle2D.Float viewBox;
69 Paint texPaint;
70
71 /**
72 * Creates a new instance of Gradient
73 */
74 public PatternSVG()
75 {
76 }
77
78 @Override
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 @Override
89 public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
90 {
91 super.loaderAddChild(helper, child);
92 }
93
94 @Override
95 protected void build() throws SVGException
96 {
97 super.build();
98
99 StyleAttribute sty = new StyleAttribute();
100
101 //Load style string
102 String href = null;
103 if (getPres(sty.setName("xlink:href")))
104 {
105 href = sty.getStringValue();
106 }
107 //String href = attrs.getValue("xlink:href");
108 //If we have a link to another pattern, initialize ourselves with it's values
109 if (href != null)
110 {
111//System.err.println("Gradient.loaderStartElement() href '" + href + "'");
112 try
113 {
114 URI src = getXMLBase().resolve(href);
115 PatternSVG patSrc = (PatternSVG) diagram.getUniverse().getElement(src);
116
117 gradientUnits = patSrc.gradientUnits;
118 x = patSrc.x;
119 y = patSrc.y;
120 width = patSrc.width;
121 height = patSrc.height;
122 viewBox = patSrc.viewBox;
123 patternXform.setTransform(patSrc.patternXform);
124 children.addAll(patSrc.children);
125 } catch (Exception e)
126 {
127 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING,
128 "Could not parse xlink:href", e);
129 }
130 }
131
132 String gradientUnits = "";
133 if (getPres(sty.setName("gradientUnits")))
134 {
135 gradientUnits = sty.getStringValue().toLowerCase();
136 }
137 if (gradientUnits.equals("userspaceonuse"))
138 {
139 this.gradientUnits = GU_USER_SPACE_ON_USE;
140 } else
141 {
142 this.gradientUnits = GU_OBJECT_BOUNDING_BOX;
143 }
144
145 String patternTransform = "";
146 if (getPres(sty.setName("patternTransform")))
147 {
148 patternTransform = sty.getStringValue();
149 }
150 patternXform = parseTransform(patternTransform);
151
152
153 if (getPres(sty.setName("x")))
154 {
155 x = sty.getFloatValueWithUnits();
156 }
157
158 if (getPres(sty.setName("y")))
159 {
160 y = sty.getFloatValueWithUnits();
161 }
162
163 if (getPres(sty.setName("width")))
164 {
165 width = sty.getFloatValueWithUnits();
166 }
167
168 if (getPres(sty.setName("height")))
169 {
170 height = sty.getFloatValueWithUnits();
171 }
172
173 if (getPres(sty.setName("viewBox")))
174 {
175 float[] dim = sty.getFloatList();
176 viewBox = new Rectangle2D.Float(dim[0], dim[1], dim[2], dim[3]);
177 }
178
179 preparePattern();
180 }
181
182 /*
183 public void loaderEndElement(SVGLoaderHelper helper)
184 {
185 build();
186 }
187 */
188 protected void preparePattern() throws SVGException
189 {
190 //For now, treat all fills as UserSpaceOnUse. Otherwise, we'll need
191 // a different paint for every object.
192 int tileWidth = (int) width;
193 int tileHeight = (int) height;
194
195 float stretchX = 1f, stretchY = 1f;
196 if (!patternXform.isIdentity())
197 {
198 //Scale our source tile so that we can have nice sampling from it.
199 float xlateX = (float) patternXform.getTranslateX();
200 float xlateY = (float) patternXform.getTranslateY();
201
202 Point2D.Float pt = new Point2D.Float(), pt2 = new Point2D.Float();
203
204 pt.setLocation(width, 0);
205 patternXform.transform(pt, pt2);
206 pt2.x -= xlateX;
207 pt2.y -= xlateY;
208 stretchX = (float) Math.sqrt(pt2.x * pt2.x + pt2.y * pt2.y) * 1.5f / width;
209
210 pt.setLocation(height, 0);
211 patternXform.transform(pt, pt2);
212 pt2.x -= xlateX;
213 pt2.y -= xlateY;
214 stretchY = (float) Math.sqrt(pt2.x * pt2.x + pt2.y * pt2.y) * 1.5f / height;
215
216 tileWidth *= stretchX;
217 tileHeight *= stretchY;
218 }
219
220 if (tileWidth == 0 || tileHeight == 0)
221 {
222 //Use defaults if tile has degenerate size
223 return;
224 }
225
226 BufferedImage buf = new BufferedImage(tileWidth, tileHeight, BufferedImage.TYPE_INT_ARGB);
227 Graphics2D g = buf.createGraphics();
228 g.setClip(0, 0, tileWidth, tileHeight);
229 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
230
231 for (SVGElement ele : children) {
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 @Override
267 public Paint getPaint(Rectangle2D bounds, AffineTransform xform)
268 {
269 return texPaint;
270 }
271
272 /**
273 * Updates all attributes in this diagram associated with a time event. Ie,
274 * all attributes with track information.
275 *
276 * @return - true if this node has changed state as a result of the time
277 * update
278 */
279 @Override
280 public boolean updateTime(double curTime) throws SVGException
281 {
282 //Patterns don't change state
283 return false;
284 }
285}
Note: See TracBrowser for help on using the repository browser.