Merge branch 'master' of http://github.com/mono/mono
[mono.git] / mcs / class / System.Drawing / System.Drawing.Drawing2D / GraphicsPathIterator.jvm.cs
1 //
2 // System.Drawing.Drawing2D.GraphicsPathIterator.cs
3 //
4 // Author:
5 // Bors Kirzner <boris@mainsoft.com>    
6 //
7 // Copyright (C) 2005 Mainsoft Corporation, (http://www.mainsoft.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 using System;
29 using System.Drawing;
30
31 namespace System.Drawing.Drawing2D
32 {
33         public sealed class GraphicsPathIterator : MarshalByRefObject, IDisposable
34         {
35                 #region Fields
36
37                 private readonly GraphicsPath _path;
38                 private int _marker = -1;
39                 private int _subpath = -1;
40
41                 #endregion // Fields
42
43                 #region Constructors
44
45                 public GraphicsPathIterator (GraphicsPath path)
46                 {
47                         _path = path;
48                 }
49
50                 #endregion // Constructors
51
52                 #region Properites
53
54                 public int Count 
55                 {
56                         get { return _path.NativeObject.PointCount; }
57                 }
58
59                 public int SubpathCount {
60                         get {
61                                 int count = 0;
62                                 int start, end;
63                                 bool isClosed;
64                                 while (NextSubpath (out start, out end, out isClosed) != 0)
65                                         count++;
66                                 return count;
67                         }
68                 }
69
70                 #endregion // Properties
71
72                 #region Methods
73
74                 public int CopyData (ref PointF [] points, ref byte [] types, int startIndex, int endIndex)
75                 {
76                         int j = 0;
77                         for (int i = startIndex; i <= endIndex && i < _path.PointCount; i++) {
78                                 points [j] = _path.PathPoints [i];
79                                 types [j++] = _path.PathTypes [i];
80                         }
81                         return j;
82                 }
83
84                 public void Dispose ()
85                 {
86                 }
87
88                 public int Enumerate (ref PointF [] points, ref byte [] types)
89                 {
90                         return CopyData (ref points, ref types, 0, _path.PointCount);
91                 }
92
93                 public bool HasCurve ()
94                 {
95                         byte [] types = _path.PathTypes;
96                         for (int i=0; i < types.Length; i++)
97                                 if ((types [i] & (byte)PathPointType.PathTypeMask) == (byte)PathPointType.Bezier3)
98                                         return true;
99                         return false;
100                 }
101
102                 public int NextMarker (GraphicsPath path)
103                 {
104                         if (path == null)
105                                 return 0;
106
107                         int startIndex;
108                         int endIndex;
109                         int count = NextMarker (out startIndex, out endIndex);
110
111                         if (count != 0)
112                                 SetPath (_path, startIndex, count, path);
113
114                         return count;
115                 }
116
117                 public int NextMarker (out int startIndex, out int endIndex)
118                 {
119                         if (_marker >= _path.PointCount) {
120                                 startIndex = 0;
121                                 endIndex = 0;
122                                 return 0;
123                         }
124
125                         startIndex = ++_marker;
126                         while ((_marker < _path.PointCount) && ((_path.PathTypes [_marker] & (byte)PathPointType.PathMarker) == 0))
127                                 _marker++;
128
129                         endIndex = (_marker < _path.PointCount) ? _marker : _path.PointCount - 1;
130                         return endIndex - startIndex + 1;
131                 }
132
133                 public int NextPathType (out byte pathType, out int startIndex, out int endIndex)
134                 {
135                         if ((_subpath >= _path.PointCount - 1) | (_subpath < 0)) {
136                                 startIndex = 0;
137                                 endIndex = 0;
138                                 pathType = (_subpath < 0) ? (byte)PathPointType.Start : _path.PathTypes [_path.PointCount - 1];
139                                 return 0;
140                         }
141
142                         // .net acts different, but it seems to be a bug
143                         if ((_path.PathTypes [_subpath + 1] & (byte)PathPointType.PathMarker) != 0) {
144                                 startIndex = 0;
145                                 endIndex = 0;
146                                 pathType = _path.PathTypes [_subpath];
147                                 return 0;
148                         }
149
150                         startIndex = _subpath++;
151                         endIndex = startIndex;
152                         pathType = (byte)(_path.PathTypes [startIndex + 1] & (byte)PathPointType.PathTypeMask);
153
154                         while (((_subpath) < _path.PointCount) && ((_path.PathTypes [_subpath] & (byte)PathPointType.PathTypeMask) == pathType))
155                                 _subpath++;
156                         
157                         endIndex = (_subpath < _path.PointCount) ? --_subpath : _path.PointCount - 1;
158                         return endIndex - startIndex + 1;
159                 }
160
161                 public int NextSubpath (GraphicsPath path, out bool isClosed)
162                 {
163                         int startIndex;
164                         int endIndex;
165                         int count = NextSubpath (out startIndex, out endIndex, out isClosed);
166
167                         if ((count != 0) && (path != null))
168                                 SetPath (_path, startIndex, count, path);
169
170                         return count;
171                 }
172
173                 private void SetPath (GraphicsPath source, int start, int count, GraphicsPath target)
174                 {
175                         PointF [] points = new PointF [count];
176                         byte [] types = new byte [count];
177                         PointF [] pathPoints = _path.PathPoints;
178                         byte [] pathTypes = _path.PathTypes;
179
180                         for (int i = 0; i < count; i++) {
181                                 points [i] = pathPoints [start + i];
182                                 types [i] = pathTypes [start + i];
183                         }
184                         
185                         target.SetPath (points, types);
186                 }
187
188                 public int NextSubpath (out int startIndex, out int endIndex, out bool isClosed)
189                 {
190                         _subpath++;
191                         while (((_subpath) < _path.PointCount) && (_path.PathTypes [_subpath] != (byte)PathPointType.Start))
192                                 _subpath++;
193
194                                 
195                         if (_subpath >= _path.PointCount - 1) {
196                                 startIndex = 0;
197                                 endIndex = 0;
198                                 isClosed = true;
199                                 return 0;
200                         }                       
201
202                         startIndex = _subpath;
203                         int offset = 1;
204                         while (((_subpath + offset) < _path.PointCount) && (_path.PathTypes [_subpath + offset] != (byte)PathPointType.Start))
205                                 offset++;
206
207                         endIndex = ((_subpath + offset) < _path.PointCount) ? _subpath + offset - 1 : _path.PointCount - 1;
208                         isClosed = (_path.PathTypes [endIndex] & (byte)PathPointType.CloseSubpath) != 0;
209                         return endIndex - startIndex + 1;
210                 }
211
212                 public void Rewind ()
213                 {
214                         _marker = -1;
215                         _subpath = -1;
216                 }
217
218                 #endregion // Methods
219         }
220 }