2ce4d614a21f0538260e994b327723c796ef9105
[mono.git] / mcs / class / System.Drawing / System.Drawing.Drawing2D / ExtendedGeneralPath.jvm.cs
1 using System;\r
2 \r
3 using java.awt;\r
4 using java.awt.geom;\r
5 using java.lang;\r
6 \r
7 namespace System.Drawing.Drawing2D\r
8 {\r
9         internal class ExtendedGeneralPath : Shape, ICloneable\r
10         {\r
11                 #region Fields\r
12 \r
13                 public const int WIND_EVEN_ODD = 0; //PathIterator__Finals.WIND_EVEN_ODD;\r
14                 public const int WIND_NON_ZERO = 1; //PathIterator__Finals.WIND_NON_ZERO;\r
15                 \r
16                 public const sbyte SEG_MOVETO  = 0; //(byte) PathIterator__Finals.SEG_MOVETO;\r
17                 public const sbyte SEG_LINETO  = 1; //(byte) PathIterator__Finals.SEG_LINETO;\r
18                 public const sbyte SEG_QUADTO  = 2; //(byte) PathIterator__Finals.SEG_QUADTO;\r
19                 public const sbyte SEG_CUBICTO = 3; //(byte) PathIterator__Finals.SEG_CUBICTO;\r
20                 public const sbyte SEG_CLOSE   = 4; //(byte) PathIterator__Finals.SEG_CLOSE;\r
21                 \r
22                 public const sbyte SEG_START      = 16; // segment start\r
23 \r
24                 public const sbyte SEG_MASK       = SEG_MOVETO | SEG_LINETO | SEG_QUADTO | SEG_CUBICTO | SEG_CLOSE; // mask to eliminate SEG_CLOSE and SEG_MARKER\r
25 \r
26                 private const sbyte SEG_MARKER = 32; // path marker\r
27                 \r
28 \r
29                 private sbyte [] _types;\r
30                 private float [] _coords;\r
31                 private int _typesCount;\r
32                 private int _coordsCount;\r
33                 private int _windingRule;\r
34 \r
35                 const int INIT_SIZE = 20;\r
36                 const int EXPAND_MAX = 500;\r
37 \r
38                 #endregion // Fileds\r
39 \r
40                 #region Constructors\r
41 \r
42             public ExtendedGeneralPath() : this (WIND_NON_ZERO, INIT_SIZE, INIT_SIZE)\r
43                 {\r
44                 }\r
45 \r
46                 public ExtendedGeneralPath(int rule) : this (rule, INIT_SIZE, INIT_SIZE)\r
47                 {\r
48                 }\r
49 \r
50                 public ExtendedGeneralPath(int rule, int initialCapacity) : this (rule, initialCapacity, initialCapacity)\r
51                 {\r
52                 }\r
53 \r
54                 public ExtendedGeneralPath(Shape s) : this(WIND_NON_ZERO, INIT_SIZE, INIT_SIZE)\r
55                 {\r
56                         PathIterator pi = s.getPathIterator (null);\r
57                         setWindingRule (pi.getWindingRule ());\r
58                         append (pi, false);\r
59                 }\r
60 \r
61                 private ExtendedGeneralPath(int rule, int initialTypes, int initialCoords) \r
62                 {\r
63                         setWindingRule(rule);\r
64                         _types = new sbyte [initialTypes];\r
65                         _coords = new float [initialCoords * 2];\r
66                 }\r
67 \r
68                 #endregion // Constructors\r
69 \r
70                 #region Properties\r
71 \r
72                 private GeneralPath GeneralPath\r
73                 {\r
74                         get {\r
75                                 PathIterator iter = getPathIterator (null);\r
76                                 GeneralPath path = new GeneralPath ();\r
77                                 path.append (iter, false);\r
78                                 return path;\r
79                         }\r
80                 }\r
81 \r
82                 public sbyte [] Types\r
83                 {\r
84                         get { return _types; }\r
85                 }\r
86 \r
87                 public float [] Coords\r
88                 {\r
89                         get { return _coords; }\r
90                 }\r
91 \r
92                 public int TypesCount\r
93                 {\r
94                         get { return _typesCount; }\r
95                 }\r
96 \r
97                 public int CoordsCount\r
98                 {\r
99                         get { return _coordsCount; }\r
100                 }\r
101 \r
102                 public bool LastFigureClosed\r
103                 {\r
104                         get { \r
105                                 return ((TypesCount == 0) || \r
106                                         ((Types [TypesCount - 1] & ExtendedGeneralPath.SEG_CLOSE) != 0) ||\r
107                                         ((Types [TypesCount - 1] & ExtendedGeneralPath.SEG_START) != 0));\r
108                         }\r
109                 }\r
110 \r
111 \r
112 \r
113                 #endregion // Properties\r
114 \r
115                 #region Methods\r
116 \r
117                 public void append(Shape s)\r
118                 {\r
119                         append (s, !LastFigureClosed);\r
120                 }\r
121 \r
122                 #region GeneralPath\r
123 \r
124                 public void append(PathIterator pi, bool connect) \r
125                 {\r
126                         float [] coords = new float [6];\r
127                         while (!pi.isDone ()) {\r
128                                 switch (pi.currentSegment (coords)) {\r
129                                         case SEG_MOVETO:\r
130                                                 if (!connect || _typesCount < 1 || _coordsCount < 2) {\r
131                                                         moveTo (coords [0], coords [1]);\r
132                                                         break;\r
133                                                 }\r
134                                                 if (_types [_typesCount - 1] != SEG_CLOSE &&\r
135                                                         _coords [_coordsCount - 2] == coords [0] &&\r
136                                                         _coords [_coordsCount - 1] == coords [1])\r
137                                                         break;  \r
138                                                 goto case SEG_LINETO;\r
139                                         case SEG_LINETO:\r
140                                                 lineTo (coords [0], coords [1]);\r
141                                                 break;\r
142                                         case SEG_QUADTO:\r
143                                                 quadTo (coords [0], coords [1], coords [2], coords [3]);\r
144                                                 break;\r
145                                         case SEG_CUBICTO:\r
146                                                 curveTo (coords [0], coords [1], coords [2], coords [3], coords [4], coords [5]);\r
147                                                 break;\r
148                                         case SEG_CLOSE:\r
149                                                 closePath ();\r
150                                         break;\r
151                                 }\r
152                                 pi.next ();\r
153                                 connect = false;\r
154                         }\r
155                 }\r
156 \r
157                 public void append(Shape s, bool connect) \r
158                 {\r
159                         PathIterator pi = s.getPathIterator (null);\r
160                         append (pi,connect);\r
161                 }\r
162 \r
163                 public object Clone() \r
164                 {\r
165                         ExtendedGeneralPath copy = new ExtendedGeneralPath ();\r
166                         copy._types = (sbyte []) _types.Clone ();\r
167                         copy._coords = (float []) _coords.Clone ();\r
168                         return copy;\r
169                 }\r
170 \r
171                 public void closePath() \r
172                 {\r
173                         if (_typesCount == 0 || _types[_typesCount - 1] != SEG_CLOSE) {\r
174                                 needRoom (1, 0, true);\r
175                                 _types [_typesCount++] = SEG_CLOSE;\r
176                         }\r
177                 }\r
178 \r
179                 public bool contains(double x, double y) \r
180                 {                       \r
181                         return GeneralPath.contains (x, y);\r
182                 }\r
183 \r
184                 public bool contains(double x, double y, double w, double h) \r
185                 {\r
186                         return GeneralPath.contains (x, y, w, h);\r
187                 }\r
188 \r
189                 public bool contains(Point2D p) \r
190                 {\r
191                         return contains (p.getX (), p.getY ());\r
192                 }\r
193 \r
194                 public bool contains(Rectangle2D r) \r
195                 {\r
196                         return contains (r.getX (), r.getY (), r.getWidth (), r.getHeight ());\r
197                 }\r
198 \r
199                 public Shape createTransformedShape(AffineTransform at) \r
200                 {\r
201                         ExtendedGeneralPath gp = (ExtendedGeneralPath) Clone ();\r
202                         if (at != null) {\r
203                                 gp.transform (at);\r
204                         }\r
205                         return gp;\r
206                 }\r
207 \r
208                 public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) \r
209                 {\r
210                         needRoom (1, 6, true);\r
211                         _types [_typesCount++] = SEG_CUBICTO;\r
212                         _coords [_coordsCount++] = x1;\r
213                         _coords [_coordsCount++] = y1;\r
214                         _coords [_coordsCount++] = x2;\r
215                         _coords [_coordsCount++] = y2;\r
216                         _coords [_coordsCount++] = x3;\r
217                         _coords [_coordsCount++] = y3;\r
218                 }\r
219 \r
220                 public java.awt.Rectangle getBounds() \r
221                 {\r
222                         return getBounds2D ().getBounds ();\r
223                 }\r
224 \r
225                 public Rectangle2D getBounds2D() \r
226                 {\r
227                         float x1, y1, x2, y2;\r
228                         int i = _coordsCount;\r
229                         if (i > 0) {\r
230                                 y1 = y2 = _coords [--i];\r
231                                 x1 = x2 = _coords [--i];\r
232                                 while (i > 0) {\r
233                                         float y = _coords [--i];\r
234                                         float x = _coords [--i];\r
235                                         if (x < x1) x1 = x;\r
236                                         if (y < y1) y1 = y;\r
237                                         if (x > x2) x2 = x;\r
238                                         if (y > y2) y2 = y;\r
239                                 }\r
240                         } \r
241                         else {\r
242                                 x1 = y1 = x2 = y2 = 0f;\r
243                         }\r
244                         return new Rectangle2D.Float (x1, y1, x2 - x1, y2 - y1);\r
245                 }\r
246 \r
247                 public Point2D getCurrentPoint() \r
248                 {\r
249                         if (_typesCount < 1 || _coordsCount < 2)\r
250                                 return null;\r
251                         \r
252                         int index = _coordsCount;\r
253                         if (_types [_typesCount - 1] == SEG_CLOSE)\r
254                                 for (int i = _typesCount - 2; i > 0; i--) {\r
255                                         switch (_types [i]) {\r
256                                                 case SEG_MOVETO:\r
257                                                         //break loop;\r
258                                                         goto loopend;\r
259                                                 case SEG_LINETO:\r
260                                                         index -= 2;\r
261                                                         break;\r
262                                                 case SEG_QUADTO:\r
263                                                         index -= 4;\r
264                                                         break;\r
265                                                 case SEG_CUBICTO:\r
266                                                         index -= 6;\r
267                                                         break;\r
268                                                 case SEG_CLOSE:\r
269                                                         break;\r
270                                         }\r
271                                 }\r
272                         loopend:\r
273 \r
274                         return new Point2D.Float (_coords [index - 2], _coords [index - 1]);\r
275                 }\r
276 \r
277                 public PathIterator getPathIterator(AffineTransform at) {\r
278                         return new GeneralPathIterator (this, at);\r
279                 }\r
280 \r
281                 public PathIterator getPathIterator(AffineTransform at, double flatness) {\r
282                         return new FlatteningPathIterator (getPathIterator (at), flatness);\r
283                 }\r
284 \r
285                 public int getWindingRule() \r
286                 {\r
287                         return _windingRule;\r
288                 }\r
289 \r
290                 public bool intersects(double x, double y, double w, double h) \r
291                 {\r
292                         return GeneralPath.intersects (x, y, w, h);\r
293                 }\r
294 \r
295                 public bool intersects(Rectangle2D r) \r
296                 {\r
297                         return intersects (r.getX (), r.getY (), r.getWidth (), r.getHeight ());\r
298                 }\r
299 \r
300                 public void lineTo(float x, float y) \r
301                 {\r
302                         needRoom (1, 2, true);\r
303                         _types [_typesCount++] = SEG_LINETO;\r
304                         _coords [_coordsCount++] = x;\r
305                         _coords [_coordsCount++] = y;\r
306                 }\r
307 \r
308                 public void moveTo(float x, float y) \r
309                 {\r
310                         if (_typesCount > 0 && _types [_typesCount - 1] == SEG_MOVETO) {\r
311                                 _coords [_coordsCount - 2] = x;\r
312                                 _coords [_coordsCount - 1] = y;\r
313                         } \r
314                         else {\r
315                                 needRoom (1, 2, false);\r
316                                 _types [_typesCount++] = SEG_MOVETO;\r
317                                 _coords [_coordsCount++] = x;\r
318                                 _coords [_coordsCount++] = y;\r
319                         }\r
320                 }\r
321 \r
322                 public void quadTo(float x1, float y1, float x2, float y2) \r
323                 {\r
324                         needRoom (1, 4, true);\r
325                         _types [_typesCount++] = SEG_QUADTO;\r
326                         _coords [_coordsCount++] = x1;\r
327                         _coords [_coordsCount++] = y1;\r
328                         _coords [_coordsCount++] = x2;\r
329                         _coords [_coordsCount++] = y2;\r
330                 }\r
331 \r
332                 public void reset() \r
333                 {\r
334                         _typesCount = 0;\r
335                         _coordsCount = 0;\r
336                 }\r
337 \r
338                 public void setWindingRule(int rule) \r
339                 {\r
340                         if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) {\r
341                                 throw new IllegalArgumentException ("winding rule must be WIND_EVEN_ODD or WIND_NON_ZERO");\r
342                         }\r
343                         _windingRule = rule;\r
344                 }\r
345 \r
346                 public void transform(AffineTransform at) \r
347                 {\r
348                         at.transform (_coords, 0, _coords, 0, _coordsCount/2);\r
349                 }\r
350 \r
351                 private void needRoom(int newTypes, int newCoords, bool needMove) \r
352                 {\r
353                         if (needMove && _typesCount == 0)\r
354                                 throw new IllegalPathStateException ("missing initial moveto in path definition");\r
355                         \r
356                         int size = _coords.Length;\r
357                         if (_coordsCount + newCoords > size) {\r
358                                 int grow = size;\r
359                                 if (grow > EXPAND_MAX * 2)\r
360                                         grow = EXPAND_MAX * 2;\r
361                                 \r
362                                 if (grow < newCoords)\r
363                                         grow = newCoords;\r
364                                 \r
365                                 float [] arr = new float [size + grow];\r
366                                 Array.Copy (_coords, 0, arr, 0, _coordsCount);\r
367                                 _coords = arr;\r
368                         }\r
369                         size = _types.Length;\r
370                         if (_typesCount + newTypes > size) {\r
371                                 int grow = size;\r
372                                 if (grow > EXPAND_MAX)\r
373                                         grow = EXPAND_MAX;\r
374                                 \r
375                                 if (grow < newTypes)\r
376                                         grow = newTypes;\r
377                                 \r
378                                 sbyte [] arr = new sbyte [size + grow];\r
379                                 Array.Copy (_types, 0, arr, 0, _typesCount);\r
380                                 _types = arr;\r
381                         }\r
382                 }\r
383 \r
384                 #endregion // GeneralPath\r
385 \r
386                 public void SetMarkers()\r
387                 {\r
388                         Types [ TypesCount - 1] |= SEG_MARKER;\r
389                 }\r
390 \r
391                 public void ClearMarkers()\r
392                 {\r
393                         for (int i = 0; i < TypesCount; i++)\r
394                                 Types [i] &= ~SEG_MARKER;\r
395                 }\r
396 \r
397                 #endregion //Methods\r
398 \r
399                 \r
400         }\r
401 }\r