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)
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
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
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
;
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. */
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.
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. */
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();
89 if (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());
103 public void moveTo(float x
, float y
)
106 ensureSize(index
+ 2);
107 types
[index
>> 1] = PathIterator
.SEG_MOVETO
;
111 public void lineTo(float x
, float y
)
113 ensureSize(index
+ 2);
114 types
[index
>> 1] = PathIterator
.SEG_LINETO
;
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
,
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];
156 int result
= i
.currentSegment(f
);
159 case PathIterator
.SEG_MOVETO
:
165 if (subpath
>= 0 && f
[0] == points
[subpath
]
166 && f
[1] == points
[subpath
+ 1])
169 case PathIterator
.SEG_LINETO
:
172 case PathIterator
.SEG_QUADTO
:
173 quadTo(f
[0], f
[1], f
[2], f
[3]);
175 case PathIterator
.SEG_CUBICTO
:
176 curveTo(f
[0], f
[1], f
[2], f
[3], f
[4], f
[5]);
185 public int getWindingRule()
189 public void setWindingRule(int rule
)
191 if (rule
!= WIND_EVEN_ODD
&& rule
!= WIND_NON_ZERO
)
192 throw new IllegalArgumentException();
196 public Point2D
getCurrentPoint()
200 return new Point2D
.Float(points
[subpath
], points
[subpath
+ 1]);
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);
219 public Rectangle
getBounds()
221 return getBounds2D().getBounds();
223 public Rectangle2D
getBounds2D()
226 throw new Error("not implemented");
229 public boolean contains(double x
, double y
)
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
)
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
)
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()
263 public int getWindingRule()
268 public boolean isDone()
270 return current
>= index
;
278 public int currentSegment(float[] coords
)
280 if (current
>= index
)
282 int result
= types
[current
>> 1];
286 coords
[i
++] = points
[current
++];
287 coords
[i
++] = points
[current
++];
291 coords
[i
++] = points
[current
++];
292 coords
[i
++] = points
[current
++];
296 coords
[i
++] = points
[current
++];
297 coords
[i
++] = points
[current
++];
299 at
.transform(coords
, 0, coords
, 0, result
== 0 ?
1 : result
);
304 public int currentSegment(double[] coords
)
306 if (current
>= index
)
308 int result
= types
[current
>> 1];
312 coords
[i
++] = points
[current
++];
313 coords
[i
++] = points
[current
++];
317 coords
[i
++] = points
[current
++];
318 coords
[i
++] = points
[current
++];
322 coords
[i
++] = points
[current
++];
323 coords
[i
++] = points
[current
++];
325 at
.transform(coords
, 0, coords
, 0, result
== 0 ?
1 : 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
342 * @exception OutOfMemoryError If there is not enough memory available.
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
)
355 throw new IllegalPathStateException("need initial moveto");
356 if (size
<= points
.length
)
358 byte[] b
= new byte[points
.length
];
359 System
.arraycopy(types
, 0, b
, 0, index
>> 1);
361 float[] f
= new float[points
.length
<< 1];
362 System
.arraycopy(points
, 0, f
, 0, index
);
365 } // class GeneralPath