FSF GCC merge 02/23/03
[official-gcc.git] / libjava / java / awt / geom / GeneralPath.java
blob6c1b578fc1931fd224904907be11307a2ca90fcf
1 /* GeneralPath.java -- represents a shape built from subpaths
2 Copyright (C) 2002 Free Software Foundation
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package java.awt.geom;
41 import java.awt.Rectangle;
42 import java.awt.Shape;
44 /**
45 * STUBS ONLY
46 * XXX Implement and document. Note that Sun's implementation only expects
47 * float precision, not double.
49 public final class GeneralPath implements Shape, Cloneable
51 public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD;
52 public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO;
54 /** Initial size if not specified. */
55 private static final int INIT_SIZE = 20;
57 /** The winding rule. */
58 private int rule;
59 /**
60 * The path type in points. Note that points[index] maps to
61 * types[index >> 1]; the control points of quad and cubic paths map as
62 * well but are ignored.
64 private byte[] types;
65 /**
66 * The list of all points seen. Since you can only append floats, it makes
67 * sense for this to be a float[]. I have no idea why Sun didn't choose to
68 * allow a general path of double precision points.
70 private float[] points;
71 /** The index of the most recent moveto point, or null. */
72 private int subpath = -1;
73 /** The next available index into points. */
74 private int index;
76 public GeneralPath()
78 this(WIND_NON_ZERO, INIT_SIZE);
80 public GeneralPath(int rule)
82 this(rule, INIT_SIZE);
84 public GeneralPath(int rule, int capacity)
86 if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO)
87 throw new IllegalArgumentException();
88 this.rule = rule;
89 if (capacity < INIT_SIZE)
90 capacity = INIT_SIZE;
91 types = new byte[capacity >> 1];
92 points = new float[capacity];
94 public GeneralPath(Shape s)
96 types = new byte[INIT_SIZE >> 1];
97 points = new float[INIT_SIZE];
98 PathIterator pi = s.getPathIterator(null);
99 setWindingRule(pi.getWindingRule());
100 append(pi, false);
103 public void moveTo(float x, float y)
105 subpath = index;
106 ensureSize(index + 2);
107 types[index >> 1] = PathIterator.SEG_MOVETO;
108 points[index++] = x;
109 points[index++] = y;
111 public void lineTo(float x, float y)
113 ensureSize(index + 2);
114 types[index >> 1] = PathIterator.SEG_LINETO;
115 points[index++] = x;
116 points[index++] = y;
118 public void quadTo(float x1, float y1, float x2, float y2)
120 ensureSize(index + 4);
121 types[index >> 1] = PathIterator.SEG_QUADTO;
122 points[index++] = x1;
123 points[index++] = y1;
124 points[index++] = x2;
125 points[index++] = y2;
127 public void curveTo(float x1, float y1, float x2, float y2,
128 float x3, float y3)
130 ensureSize(index + 6);
131 types[index >> 1] = PathIterator.SEG_QUADTO;
132 points[index++] = x1;
133 points[index++] = y1;
134 points[index++] = x2;
135 points[index++] = y2;
136 points[index++] = x3;
137 points[index++] = y3;
139 public void closePath()
141 ensureSize(index + 2);
142 types[index >> 1] = PathIterator.SEG_CLOSE;
143 points[index++] = points[subpath];
144 points[index++] = points[subpath + 1];
147 public void append(Shape s, boolean connect)
149 append(s.getPathIterator(null), connect);
151 public void append(PathIterator i, boolean connect)
153 float[] f = new float[6];
154 while (! i.isDone())
156 int result = i.currentSegment(f);
157 switch (result)
159 case PathIterator.SEG_MOVETO:
160 if (! connect)
162 moveTo(f[0], f[1]);
163 break;
165 if (subpath >= 0 && f[0] == points[subpath]
166 && f[1] == points[subpath + 1])
167 break;
168 // Fallthrough.
169 case PathIterator.SEG_LINETO:
170 lineTo(f[0], f[1]);
171 break;
172 case PathIterator.SEG_QUADTO:
173 quadTo(f[0], f[1], f[2], f[3]);
174 break;
175 case PathIterator.SEG_CUBICTO:
176 curveTo(f[0], f[1], f[2], f[3], f[4], f[5]);
177 break;
178 default:
179 closePath();
181 connect = false;
185 public int getWindingRule()
187 return rule;
189 public void setWindingRule(int rule)
191 if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO)
192 throw new IllegalArgumentException();
193 this.rule = rule;
196 public Point2D getCurrentPoint()
198 if (subpath < 0)
199 return null;
200 return new Point2D.Float(points[subpath], points[subpath + 1]);
202 public void reset()
204 subpath = -1;
205 index = 0;
208 public void transform(AffineTransform xform)
210 xform.transform(points, 0, points, 0, index >> 1);
212 public Shape createTransformedShape(AffineTransform xform)
214 GeneralPath p = new GeneralPath(this);
215 p.transform(xform);
216 return p;
219 public Rectangle getBounds()
221 return getBounds2D().getBounds();
223 public Rectangle2D getBounds2D()
225 // XXX Implement.
226 throw new Error("not implemented");
229 public boolean contains(double x, double y)
231 // XXX Implement.
232 throw new Error("not implemented");
234 public boolean contains(Point2D p)
236 return contains(p.getX(), p.getY());
238 public boolean contains(double x, double y, double w, double h)
240 // XXX Implement.
241 throw new Error("not implemented");
243 public boolean contains(Rectangle2D r)
245 return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
248 public boolean intersects(double x, double y, double w, double h)
250 // XXX Implement.
251 throw new Error("not implemented");
253 public boolean intersects(Rectangle2D r)
255 return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
257 public PathIterator getPathIterator(final AffineTransform at)
259 return new PathIterator()
261 int current = 0;
263 public int getWindingRule()
265 return rule;
268 public boolean isDone()
270 return current >= index;
273 public void next()
275 current++;
278 public int currentSegment(float[] coords)
280 if (current >= index)
281 return SEG_CLOSE;
282 int result = types[current >> 1];
283 int i = 0;
284 if (result == 3)
286 coords[i++] = points[current++];
287 coords[i++] = points[current++];
289 if (result == 2)
291 coords[i++] = points[current++];
292 coords[i++] = points[current++];
294 if (result < 2)
296 coords[i++] = points[current++];
297 coords[i++] = points[current++];
298 if (at != null)
299 at.transform(coords, 0, coords, 0, result == 0 ? 1 : result);
301 return result;
304 public int currentSegment(double[] coords)
306 if (current >= index)
307 return SEG_CLOSE;
308 int result = types[current >> 1];
309 int i = 0;
310 if (result == 3)
312 coords[i++] = points[current++];
313 coords[i++] = points[current++];
315 if (result == 2)
317 coords[i++] = points[current++];
318 coords[i++] = points[current++];
320 if (result < 2)
322 coords[i++] = points[current++];
323 coords[i++] = points[current++];
324 if (at != null)
325 at.transform(coords, 0, coords, 0, result == 0 ? 1 : result);
327 return result;
331 public PathIterator getPathIterator(AffineTransform at, double flatness)
333 return new FlatteningPathIterator(getPathIterator(at), flatness);
337 * Create a new shape of the same run-time type with the same contents as
338 * this one.
340 * @return the clone
342 * @exception OutOfMemoryError If there is not enough memory available.
344 * @since 1.2
346 public Object clone()
348 // This class is final; no need to use super.clone().
349 return new GeneralPath(this);
352 private void ensureSize(int size)
354 if (subpath < 0)
355 throw new IllegalPathStateException("need initial moveto");
356 if (size <= points.length)
357 return;
358 byte[] b = new byte[points.length];
359 System.arraycopy(types, 0, b, 0, index >> 1);
360 types = b;
361 float[] f = new float[points.length << 1];
362 System.arraycopy(points, 0, f, 0, index);
363 points = f;
365 } // class GeneralPath