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

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

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

File size: 7.5 KB
Line 
1/*
2 * To change this template, choose Tools | Templates
3 * and open the template in the editor.
4 */
5
6package com.kitfox.svg;
7
8import com.kitfox.svg.xml.StyleAttribute;
9import java.awt.Graphics2D;
10import java.awt.Rectangle;
11import java.awt.Shape;
12import java.awt.geom.AffineTransform;
13import java.awt.geom.PathIterator;
14import java.awt.geom.Rectangle2D;
15import java.util.ArrayList;
16
17/**
18 *
19 * @author kitfox
20 */
21public class Marker extends Group
22{
23 AffineTransform viewXform;
24 AffineTransform markerXform;
25 Rectangle2D viewBox;
26
27 float refX;
28 float refY;
29 float markerWidth = 3;
30 float markerHeight = 3;
31 float orient = Float.NaN;
32
33 protected void build() throws SVGException
34 {
35 super.build();
36
37 StyleAttribute sty = new StyleAttribute();
38
39 if (getPres(sty.setName("refX"))) refX = sty.getFloatValueWithUnits();
40 if (getPres(sty.setName("refY"))) refY = sty.getFloatValueWithUnits();
41 if (getPres(sty.setName("markerWidth"))) markerWidth = sty.getFloatValueWithUnits();
42 if (getPres(sty.setName("markerHeight"))) markerHeight = sty.getFloatValueWithUnits();
43
44 if (getPres(sty.setName("orient")))
45 {
46 if ("auto".equals(sty.getStringValue()))
47 {
48 orient = Float.NaN;
49 }
50 else
51 {
52 orient = sty.getFloatValue();
53 }
54 }
55
56 if (getPres(sty.setName("viewBox")))
57 {
58 float[] dim = sty.getFloatList();
59 viewBox = new Rectangle2D.Float(dim[0], dim[1], dim[2], dim[3]);
60 }
61
62 if (viewBox == null)
63 {
64 viewBox = new Rectangle(0, 0, 1, 1);
65 }
66
67 //Transform pattern onto unit square
68 viewXform = new AffineTransform();
69 viewXform.scale(1.0 / viewBox.getWidth(), 1.0 / viewBox.getHeight());
70 viewXform.translate(-viewBox.getX(), -viewBox.getY());
71
72 markerXform = new AffineTransform();
73 markerXform.scale(markerWidth, markerHeight);
74 markerXform.concatenate(viewXform);
75 markerXform.translate(-refX, -refY);
76 }
77
78 protected boolean outsideClip(Graphics2D g) throws SVGException
79 {
80 g.getClipBounds(clipBounds);
81 Rectangle2D rect = super.getBoundingBox();
82 if (rect.intersects(clipBounds))
83 {
84 return false;
85 }
86
87 return true;
88
89 }
90
91 public void render(Graphics2D g) throws SVGException
92 {
93 AffineTransform oldXform = g.getTransform();
94 g.transform(markerXform);
95
96 super.render(g);
97
98 g.setTransform(oldXform);
99 }
100
101 public void render(Graphics2D g, MarkerPos pos, float strokeWidth) throws SVGException
102 {
103 AffineTransform cacheXform = g.getTransform();
104
105 g.translate(pos.x, pos.y);
106 g.scale(strokeWidth, strokeWidth);
107 g.rotate(Math.atan2(pos.dy, pos.dx));
108
109 g.transform(markerXform);
110
111 super.render(g);
112
113 g.setTransform(cacheXform);
114 }
115
116 public Shape getShape()
117 {
118 Shape shape = super.getShape();
119 return markerXform.createTransformedShape(shape);
120 }
121
122 public Rectangle2D getBoundingBox() throws SVGException
123 {
124 Rectangle2D rect = super.getBoundingBox();
125 return markerXform.createTransformedShape(rect).getBounds2D();
126 }
127
128 /**
129 * Updates all attributes in this diagram associated with a time event.
130 * Ie, all attributes with track information.
131 * @return - true if this node has changed state as a result of the time
132 * update
133 */
134 public boolean updateTime(double curTime) throws SVGException
135 {
136 boolean changeState = super.updateTime(curTime);
137
138 //Marker properties do not change
139 return changeState;
140 }
141
142 //--------------------------------
143 public static final int MARKER_START = 0;
144 public static final int MARKER_MID = 1;
145 public static final int MARKER_END = 2;
146
147 public static class MarkerPos
148 {
149 int type;
150 double x;
151 double y;
152 double dx;
153 double dy;
154
155 public MarkerPos(int type, double x, double y, double dx, double dy)
156 {
157 this.type = type;
158 this.x = x;
159 this.y = y;
160 this.dx = dx;
161 this.dy = dy;
162 }
163 }
164
165 public static class MarkerLayout
166 {
167 private ArrayList markerList = new ArrayList();
168 boolean started = false;
169
170 public void layout(Shape shape)
171 {
172 double px = 0;
173 double py = 0;
174 double[] coords = new double[6];
175 for (PathIterator it = shape.getPathIterator(null);
176 !it.isDone(); it.next())
177 {
178 switch (it.currentSegment(coords))
179 {
180 case PathIterator.SEG_MOVETO:
181 px = coords[0];
182 py = coords[1];
183 started = false;
184 break;
185 case PathIterator.SEG_CLOSE:
186 started = false;
187 break;
188 case PathIterator.SEG_LINETO:
189 {
190 double x = coords[0];
191 double y = coords[1];
192 markerIn(px, py, x - px, y - py);
193 markerOut(x, y, x - px, y - py);
194 px = x;
195 py = y;
196 break;
197 }
198 case PathIterator.SEG_QUADTO:
199 {
200 double k0x = coords[0];
201 double k0y = coords[1];
202 double x = coords[2];
203 double y = coords[3];
204 markerIn(px, py, k0x - px, k0y - py);
205 markerOut(x, y, x - k0x, y - k0y);
206 px = x;
207 py = y;
208 break;
209 }
210 case PathIterator.SEG_CUBICTO:
211 {
212 double k0x = coords[0];
213 double k0y = coords[1];
214 double k1x = coords[2];
215 double k1y = coords[3];
216 double x = coords[4];
217 double y = coords[5];
218 markerIn(px, py, k0x - px, k0y - py);
219 markerOut(x, y, x - k1x, y - k1y);
220 px = x;
221 py = y;
222 break;
223 }
224 }
225 }
226
227 for (int i = 1; i < markerList.size(); ++i)
228 {
229 MarkerPos prev = (MarkerPos)markerList.get(i - 1);
230 MarkerPos cur = (MarkerPos)markerList.get(i);
231
232 if (cur.type == MARKER_START)
233 {
234 prev.type = MARKER_END;
235 }
236 }
237 MarkerPos last = (MarkerPos)markerList.get(markerList.size() - 1);
238 last.type = MARKER_END;
239 }
240
241 private void markerIn(double x, double y, double dx, double dy)
242 {
243 if (started == false)
244 {
245 started = true;
246 markerList.add(new MarkerPos(MARKER_START, x, y, dx, dy));
247 }
248 }
249
250 private void markerOut(double x, double y, double dx, double dy)
251 {
252 markerList.add(new MarkerPos(MARKER_MID, x, y, dx, dy));
253 }
254
255 /**
256 * @return the markerList
257 */
258 public ArrayList getMarkerList()
259 {
260 return markerList;
261 }
262 }
263}
Note: See TracBrowser for help on using the repository browser.