Prechádzať zdrojové kódy

Initial commit

svn path=/trunk/mcs/; revision=47999
Andrew Skiba 20 rokov pred
rodič
commit
d3d5a72bc9
29 zmenil súbory, kde vykonal 8835 pridanie a 0 odobranie
  1. 3 0
      mcs/class/System.Drawing/Test/DrawingTest/ChangeLog
  2. 58 0
      mcs/class/System.Drawing/Test/DrawingTest/DrawingTestHelper/AssemblyInfo.cs
  3. 509 0
      mcs/class/System.Drawing/Test/DrawingTest/DrawingTestHelper/DrawingTest.cs
  4. 104 0
      mcs/class/System.Drawing/Test/DrawingTest/DrawingTestHelper/DrawingTestHelper.csproj
  5. 28 0
      mcs/class/System.Drawing/Test/DrawingTest/DrawingTestHelper/DrawingTestHelper_java.vmwcsproj
  6. 10 0
      mcs/class/System.Drawing/Test/DrawingTest/DrawingTestHelper/Makefile
  7. 10 0
      mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/Makefile
  8. 1124 0
      mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/doc/Exocortex.DSP.xml
  9. 58 0
      mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/AssemblyInfo.cs
  10. 527 0
      mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/Complex.cs
  11. 682 0
      mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/ComplexArray.cs
  12. 520 0
      mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/ComplexF.cs
  13. 158 0
      mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/ComplexMath.cs
  14. 306 0
      mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/ComplexStats.cs
  15. 135 0
      mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/Exocortex.DSP.v1.csproj
  16. 1346 0
      mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/Fourier.cs
  17. 55 0
      mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/FourierDirection.cs
  18. 58 0
      mcs/class/System.Drawing/Test/DrawingTest/Test/AssemblyInfo.cs
  19. 51 0
      mcs/class/System.Drawing/Test/DrawingTest/Test/Bitmap.cs
  20. BIN
      mcs/class/System.Drawing/Test/DrawingTest/Test/Bitmap1.png
  21. 31 0
      mcs/class/System.Drawing/Test/DrawingTest/Test/Brush.cs
  22. 1951 0
      mcs/class/System.Drawing/Test/DrawingTest/Test/Graphics.cs
  23. 202 0
      mcs/class/System.Drawing/Test/DrawingTest/Test/Image.cs
  24. 17 0
      mcs/class/System.Drawing/Test/DrawingTest/Test/Makefile
  25. 267 0
      mcs/class/System.Drawing/Test/DrawingTest/Test/Pen.cs
  26. 214 0
      mcs/class/System.Drawing/Test/DrawingTest/Test/Region.cs
  27. BIN
      mcs/class/System.Drawing/Test/DrawingTest/Test/SampIcon.ico
  28. 335 0
      mcs/class/System.Drawing/Test/DrawingTest/Test/Test.dotnet.csproj
  29. 76 0
      mcs/class/System.Drawing/Test/DrawingTest/Test/Test.vmwcsproj

+ 3 - 0
mcs/class/System.Drawing/Test/DrawingTest/ChangeLog

@@ -0,0 +1,3 @@
+2005-08-04 Andrew Skiba <[email protected]>
+
+	Initial commit

+ 58 - 0
mcs/class/System.Drawing/Test/DrawingTest/DrawingTestHelper/AssemblyInfo.cs

@@ -0,0 +1,58 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]		
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the 
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing. 
+//
+// Notes: 
+//   (*) If no key is specified, the assembly is not signed.
+//   (*) KeyName refers to a key that has been installed in the Crypto Service
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains
+//       a key.
+//   (*) If the KeyFile and the KeyName values are both specified, the 
+//       following processing occurs:
+//       (1) If the KeyName can be found in the CSP, that key is used.
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key 
+//           in the KeyFile is installed into the CSP and used.
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+//       When specifying the KeyFile, the location of the KeyFile should be
+//       relative to the project output directory which is
+//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+//       located in the project directory, you would specify the AssemblyKeyFile 
+//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+//       documentation for more information on this.
+//
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]

+ 509 - 0
mcs/class/System.Drawing/Test/DrawingTest/DrawingTestHelper/DrawingTest.cs

@@ -0,0 +1,509 @@
+using System;
+using System.Drawing;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using Exocortex.DSP;
+using System.Reflection;
+using System.Xml.Serialization;
+using System.Collections;
+using System.Security.Cryptography;
+
+#if TARGET_JVM
+using awt = java.awt;
+using javax.imageio;
+using java.lang;
+using java.security;
+using java.awt.image;
+#else
+using System.Windows.Forms;
+using System.Drawing.Imaging;
+using System.Runtime.InteropServices;
+#endif
+
+namespace DrawingTestHelper
+{
+	#region Results serialization classes
+	public sealed class ExpectedResult {
+		public ExpectedResult(){}
+		public ExpectedResult(string testName, double norm) {
+			TestName = testName;
+			Norm = norm;
+		}
+		public string TestName;
+		public double Norm;
+	}
+
+	public sealed class ExpectedResults {
+		[XmlArrayItem(typeof(ExpectedResult))]
+		public ArrayList Tests = new ArrayList();
+	}
+
+	public sealed class ExpectedResultsHash {
+		Hashtable _hash;
+		ExpectedResults _suite;
+
+		public ExpectedResultsHash () {
+			try {
+				using (StreamReader s = new StreamReader (FileName)) {
+					_suite = (ExpectedResults)TestSuiteSerializer.Deserialize(s);
+				}
+			}
+			catch {
+				_suite = new ExpectedResults ();
+			}
+			_hash = new Hashtable(_suite.Tests.Count);
+			foreach (ExpectedResult res in _suite.Tests)
+				_hash[res.TestName] = res.Norm;
+		}
+
+		public const string FileName = "ExpectedResults.xml";
+		public readonly static XmlSerializer TestSuiteSerializer = new XmlSerializer(typeof(ExpectedResults));
+
+		public double GetNorm(string testName) {
+			object res = _hash[testName];
+			if (res != null)
+				return (double)res;
+			return double.NaN;
+		}
+
+		public void WriteNorm (string testName, double myNorm) {
+			if (_hash.Contains (testName)) {
+				for (int i = 0; i < _suite.Tests.Count; i++) {
+					ExpectedResult cur = (ExpectedResult) _suite.Tests[i];
+					if (cur.TestName == testName) {
+						cur.Norm = myNorm;
+						break;
+					}
+				}
+			}
+			else
+				_suite.Tests.Add(new ExpectedResult(testName, myNorm));
+
+			_hash[testName] = myNorm;
+			using(StreamWriter w = new StreamWriter(FileName))
+				TestSuiteSerializer.Serialize(w, _suite);
+		}
+	}
+
+	public sealed class CachedResult {
+		public CachedResult (){}
+		public CachedResult (string testName, string sha1, double norm) {
+			TestName = testName;
+			SHA1 = sha1;
+			Norm = norm;
+			DateTime = DateTime.Now;
+		}
+
+		public string TestName;
+		public string SHA1;
+		public double Norm;
+		public DateTime DateTime;
+	}
+
+	public sealed class CachedResults {
+		[XmlArrayItem(typeof(CachedResult))]
+		public ArrayList Tests = new ArrayList();
+	}
+
+	public class Cache {
+		Hashtable _hash;
+		CachedResults _results;
+
+#if TARGET_JVM
+		public const string FileName = "CachedResults.xml";
+		public const string NewFileName = "NewCachedResults.xml";
+#else
+		public const string FileName = "dotnet.CachedResults.xml";
+		public const string NewFileName = "dotnet.NewCachedResults.xml";
+#endif
+		public readonly static XmlSerializer TestSuiteSerializer =
+			new XmlSerializer(typeof(CachedResults));
+
+		public Cache () {
+			try {
+				using (StreamReader r = new StreamReader(FileName))
+					_results = (CachedResults)TestSuiteSerializer.Deserialize(r);
+			}
+			catch {
+				_results = new CachedResults ();
+			}
+			
+			_hash = new Hashtable(_results.Tests.Count);
+			foreach (CachedResult res in _results.Tests)
+				_hash[res.SHA1] = res.Norm;
+		}
+
+		public double GetNorm (string sha1) {
+			if (_hash.ContainsKey (sha1))
+				return (double)_hash[sha1];
+			else
+				return double.NaN;
+		}
+
+		public void Add (string testName, string sha1, double norm) {
+			if (_hash.ContainsKey (sha1))
+				throw new ArgumentException ("This SHA1 is already in the cache", "sha1");
+
+			_results.Tests.Add (new CachedResult(testName, sha1, norm));
+			_hash.Add (sha1, norm);
+
+			using(StreamWriter w = new StreamWriter(NewFileName))
+				TestSuiteSerializer.Serialize(w, _results);
+		}
+	}
+	#endregion
+
+	/// <summary>
+	/// Summary description for DrawingTest.
+	/// </summary>
+	public abstract class DrawingTest {
+		Graphics _graphics;
+		protected Bitmap _bitmap;
+		static string _callingFunction;
+		//static int _counter;
+		static Hashtable _mpFuncCount = new Hashtable();
+		static bool _showForms = false;
+		static bool _createResults = true;
+
+		protected readonly static ExpectedResultsHash ExpectedResults = new ExpectedResultsHash ();
+		protected readonly static Cache cache = new Cache ();
+
+		public Graphics Graphics {get {return _graphics;}}
+		public Bitmap Bitmap {get { return _bitmap; }}
+
+		public static bool ShowForms {
+			get {return _showForms;}
+			set {_showForms = value;}
+		}
+
+		public static bool CreateResults {
+			get {return _createResults;}
+			set {_createResults = value;}
+		}
+
+		protected DrawingTest() {}
+		
+		private void Init (int width, int height) {
+			Init (new Bitmap (width, height));
+		}
+
+		private void Init (Bitmap bitmap) {
+			_bitmap = bitmap;
+			_graphics = Graphics.FromImage (_bitmap);
+		}
+
+		protected abstract string DetermineCallingFunction ();
+
+		protected interface IMyForm {
+			void Show ();
+		}
+
+		protected abstract IMyForm CreateForm (string title);
+
+		public void Show () {
+			CheckCounter ();
+			if (!ShowForms)
+				return;
+			IMyForm form = CreateForm(_callingFunction + _mpFuncCount[_callingFunction]);
+			form.Show ();
+		}
+	
+		static protected string TestName {
+			get {
+				return _callingFunction + ":" + _mpFuncCount[_callingFunction]/* + ".dat"*/;
+			}
+		}
+
+		#region GetImageFFTArray
+		private static ComplexF[] GetImageFFTArray(Bitmap bitmap) {
+			float scale = 1F / (float) System.Math.Sqrt(bitmap.Width * bitmap.Height);
+			ComplexF[] data = new ComplexF [bitmap.Width * bitmap.Height * 4];
+
+			int offset = 0;
+			for( int y = 0; y < bitmap.Height; y ++ )
+				for( int x = 0; x < bitmap.Width; x ++ ) {
+					Color c = bitmap.GetPixel (x, y);
+					float s = 1F;
+					if( (( x + y ) & 0x1 ) != 0 ) {
+						s = -1F;
+					}
+
+					data [offset++] = new ComplexF( c.A * s / 256F, 0);
+					data [offset++] = new ComplexF( c.R * s / -256F, 0);
+					data [offset++] = new ComplexF( c.G * s / 256F, 0);
+					data [offset++] = new ComplexF( c.B * s / -256F, 0);
+				}
+			
+
+			Fourier.FFT3( data, 4, bitmap.Width, bitmap.Height, FourierDirection.Forward );
+			
+			for( int i = 0; i < data.Length; i ++ ) {
+				data[i] *= scale;
+			}
+
+			return data;
+		}
+		#endregion
+
+		abstract public string CalculateSHA1 ();
+		
+		public static double CalculateNorm (Bitmap bitmap) {
+			ComplexF[] matrix = GetImageFFTArray(bitmap);
+
+			double norm = 0;
+			int size_x = 4; //ARGB values
+			int size_y = bitmap.Width;
+			int size_z = bitmap.Height;
+			for (int x=1; x<=size_x; x++) {
+				double norm_y = 0;
+				for (int y=1; y<=size_y; y++) {
+					double norm_z = 0;
+					for (int z=1; z<=size_z; z++) {
+						ComplexF cur = matrix[(size_x-x)+size_x*(size_y-y)+size_x*size_y*(size_z-z)];
+						norm_z += cur.GetModulusSquared ();// * z;
+					}
+					norm_y += norm_z;// * y;
+				}
+				norm += norm_y;// * x;
+			}
+			return norm;
+		}
+
+		public double GetNorm () {
+			string sha1 = CalculateSHA1 ();
+
+			double norm = cache.GetNorm (sha1);
+			if (double.IsNaN (norm)) {
+				norm = CalculateNorm (_bitmap);
+				cache.Add (TestName, sha1, norm);
+			}
+			return norm;
+		}
+
+		protected abstract double GetExpectedNorm (double myNorm);
+
+		private void CheckCounter () {
+			string callFunc = DetermineCallingFunction ();
+			_callingFunction = callFunc;
+			if (!_mpFuncCount.Contains(_callingFunction)) {
+				
+				_mpFuncCount[_callingFunction] = 1;
+			}
+			else {
+				int counter = (int)_mpFuncCount[_callingFunction];
+				counter ++;
+				_mpFuncCount[_callingFunction] = counter;
+			}
+		}
+
+		/// <summary>
+		/// Checks that the given bitmap norm is similar to expected
+		/// </summary>
+		/// <param name="tolerance">tolerance in percents (0..100)</param>
+		/// <returns></returns>
+		public bool Compare (double tolerance) {
+			CheckCounter ();
+			return (CompareToExpectedInternal()*100) < tolerance;
+		}
+		
+		public double CompareToExpected () {
+			CheckCounter ();
+			return CompareToExpectedInternal ();
+		}
+
+		double CompareToExpectedInternal () {
+			if (ShowForms)
+				return 0;
+
+			double norm = GetNorm ();
+			double expNorm = GetExpectedNorm (norm);
+			return System.Math.Abs (norm-expNorm)/(norm+expNorm+double.Epsilon);
+		}
+
+		public static DrawingTest Create (int width, int height) {
+			DrawingTest test;
+#if TARGET_JVM
+			test = new JavaDrawingTest ();
+#else
+			test = new NetDrawingTest ();
+#endif
+			test.Init (width, height);
+			return test;
+		}
+	}
+
+#if TARGET_JVM
+	internal class JavaDrawingTest:DrawingTest {
+		java.awt.image.BufferedImage _image;
+		java.awt.image.BufferedImage Image {
+			get {
+				if (_image != null)
+					return _image;
+				Type imageType = typeof (Image);
+				PropertyInfo prop = imageType.GetProperty ("NativeObject",
+					BindingFlags.NonPublic | BindingFlags.Instance);
+				MethodInfo method = prop.GetGetMethod (true);
+				_image = (java.awt.image.BufferedImage) method.Invoke (_bitmap, new object [0]);
+				return _image;
+			}
+		}
+
+		public JavaDrawingTest () {}
+
+		protected override double GetExpectedNorm (double myNorm) {
+			return ExpectedResults.GetNorm(TestName);
+		}
+
+		private class JavaForm:java.awt.Dialog,IMyForm {
+			class EventListener : [email protected] {
+				#region WindowListener Members
+
+				public void windowOpened([email protected] arg_0) {
+					// TODO:  Add ttt.windowOpened implementation
+				}
+
+				public void windowActivated([email protected] arg_0) {
+					// TODO:  Add ttt.windowActivated implementation
+				}
+
+				public void windowClosed([email protected] arg_0) {
+					// TODO:  Add ttt.windowClosed implementation
+				}
+
+				public void windowDeiconified([email protected] arg_0) {
+					// TODO:  Add ttt.windowDeiconified implementation
+				}
+
+				public void windowIconified([email protected] arg_0) {
+					// TODO:  Add ttt.windowIconified implementation
+				}
+
+				public void windowClosing([email protected] arg_0) {
+					// TODO:  Add ttt.windowClosing implementation
+					java.awt.Window w = arg_0.getWindow();
+					java.awt.Window par = w.getOwner ();
+					w.dispose();
+					par.dispose ();
+				}
+
+				public void windowDeactivated([email protected] arg_0) {
+					// TODO:  Add ttt.windowDeactivated implementation
+				}
+
+				#endregion
+			}
+
+			java.awt.Image _image;
+			Size _s;
+
+			public JavaForm (string title, java.awt.Image anImage, Size s)
+				: base(new java.awt.Frame(), title, true) {
+				_image = anImage;
+				_s = s;
+				
+				addWindowListener(new EventListener());
+			}
+			public override void paint (java.awt.Graphics g) {
+				base.paint (g);
+				awt.Insets insets = this.getInsets ();
+				g.drawImage (_image, insets.left, insets.top, null);
+			}
+			void IMyForm.Show () {
+				awt.Insets insets = this.getInsets ();
+				base.setSize (_s.Width + insets.left + insets.right,
+					_s.Width + insets.top + insets.bottom);
+				this.show ();
+				//save the image
+				//ImageIO.write((java.awt.image.RenderedImage)_image, "png", new java.io.File("test.java.png"));
+			}
+		}
+
+		protected override IMyForm CreateForm(string title) {
+			return new JavaForm (title, Image, _bitmap.Size);
+		}
+		
+		protected override string DetermineCallingFunction() {
+			System.Exception e = new System.Exception ();
+			java.lang.Class c = vmw.common.TypeUtils.ToClass (e);
+			java.lang.reflect.Method m = c.getMethod ("getStackTrace",
+				new java.lang.Class [0]);
+			java.lang.StackTraceElement [] els = (java.lang.StackTraceElement [])
+				m.invoke (e, new object [0]);
+			java.lang.StackTraceElement el = els [4];
+			return el.getClassName () + "." + el.getMethodName ();
+		}
+
+		public override string CalculateSHA1() {
+			MessageDigest md = MessageDigest.getInstance ("SHA");
+			DataBufferInt dbi = (DataBufferInt) Image.getRaster ().getDataBuffer ();
+			for (int i=0; i<dbi.getNumBanks (); i++) {
+				int [] curBank = dbi.getData (i);
+				for (int j=0; j<curBank.Length; j++) {
+					int x = curBank[j];
+					md.update ((sbyte) (x & 0xFF));
+					md.update ((sbyte) ((x>>8) & 0xFF));
+					md.update ((sbyte) ((x>>16) & 0xFF));
+					md.update ((sbyte) ((x>>24) & 0xFF));
+				}
+			}
+			
+			return md.ToString ();
+		}
+	}
+#else
+	internal class NetDrawingTest:DrawingTest {
+		public NetDrawingTest () {}
+
+		protected override double GetExpectedNorm (double myNorm) {
+			if (CreateResults)
+				ExpectedResults.WriteNorm (TestName, myNorm);
+
+			return myNorm;
+		}
+
+		private class NetForm:Form,IMyForm {
+			Image image;
+			public NetForm(string title, Image anImage):base() {
+				base.Text = title;
+				image = anImage;
+			}
+			protected override void OnPaint(PaintEventArgs e) {
+				e.Graphics.DrawImageUnscaled (image, 0, 0);
+			}
+			void IMyForm.Show () {
+				this.Size = image.Size;
+				this.ShowDialog ();
+				this.image.Save("test.net.png");
+			}
+		}
+		protected override IMyForm CreateForm(string title) {
+			return new NetForm (title, _bitmap);
+		}
+
+		protected override string DetermineCallingFunction() {
+			StackFrame sf = new StackFrame (3, true);
+			MethodBase mb = sf.GetMethod ();
+
+			string name = mb.DeclaringType.FullName + "." + mb.Name;
+			return name;
+		}
+
+		public override string CalculateSHA1() {
+			Rectangle r = new Rectangle(0, 0, _bitmap.Width, _bitmap.Height);
+			
+			BitmapData data = _bitmap.LockBits (r, ImageLockMode.ReadOnly,
+				_bitmap.PixelFormat);
+			int dataSize = data.Stride * data.Height;
+			byte [] bdata = new byte [dataSize];
+			Marshal.Copy (data.Scan0, bdata, 0, dataSize);
+			_bitmap.UnlockBits (data);
+
+			SHA1 sha1 = new SHA1CryptoServiceProvider ();
+			byte [] resdata = sha1.ComputeHash (bdata);
+			return Convert.ToBase64String (resdata);
+		}
+
+	}
+#endif
+}

+ 104 - 0
mcs/class/System.Drawing/Test/DrawingTest/DrawingTestHelper/DrawingTestHelper.csproj

@@ -0,0 +1,104 @@
+<VisualStudioProject>
+    <CSHARP
+        ProjectType = "Local"
+        ProductVersion = "7.10.3077"
+        SchemaVersion = "2.0"
+        ProjectGuid = "{8EF9FC71-4D70-4F89-BF4D-B83EF37D4A0C}"
+        SccProjectName = "SAK"
+        SccLocalPath = "..\..\..\..\.."
+        SccProvider = "MSSCCI:ClearCase"
+    >
+        <Build>
+            <Settings
+                ApplicationIcon = ""
+                AssemblyKeyContainerName = ""
+                AssemblyName = "DrawingTest"
+                AssemblyOriginatorKeyFile = ""
+                DefaultClientScript = "JScript"
+                DefaultHTMLPageLayout = "Grid"
+                DefaultTargetSchema = "IE50"
+                DelaySign = "false"
+                OutputType = "Library"
+                PreBuildEvent = ""
+                PostBuildEvent = ""
+                RootNamespace = "DrawingTest"
+                RunPostBuildEvent = "OnBuildSuccess"
+                StartupObject = ""
+            >
+                <Config
+                    Name = "Debug"
+                    AllowUnsafeBlocks = "false"
+                    BaseAddress = "285212672"
+                    CheckForOverflowUnderflow = "false"
+                    ConfigurationOverrideFile = ""
+                    DefineConstants = "DEBUG;TRACE"
+                    DocumentationFile = ""
+                    DebugSymbols = "true"
+                    FileAlignment = "4096"
+                    IncrementalBuild = "false"
+                    NoStdLib = "false"
+                    NoWarn = "1595"
+                    Optimize = "false"
+                    OutputPath = "..\bin\Debug_Java\"
+                    RegisterForComInterop = "false"
+                    RemoveIntegerChecks = "false"
+                    TreatWarningsAsErrors = "false"
+                    WarningLevel = "4"
+                />
+                <Config
+                    Name = "Release"
+                    AllowUnsafeBlocks = "false"
+                    BaseAddress = "285212672"
+                    CheckForOverflowUnderflow = "false"
+                    ConfigurationOverrideFile = ""
+                    DefineConstants = "TRACE"
+                    DocumentationFile = ""
+                    DebugSymbols = "false"
+                    FileAlignment = "4096"
+                    IncrementalBuild = "false"
+                    NoStdLib = "false"
+                    NoWarn = "1595"
+                    Optimize = "true"
+                    OutputPath = "..\bin\Release_Java\"
+                    RegisterForComInterop = "false"
+                    RemoveIntegerChecks = "false"
+                    TreatWarningsAsErrors = "false"
+                    WarningLevel = "4"
+                />
+            </Settings>
+            <References>
+                <Reference
+                    Name = "System"
+                    AssemblyName = "System"
+                    HintPath = "..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
+                />
+                <Reference
+                    Name = "System.Drawing"
+                    AssemblyName = "System.Drawing"
+                    HintPath = "..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Drawing.dll"
+                    Private = "False"
+                />
+                <Reference
+                    Name = "System.Windows.Forms"
+                    AssemblyName = "System.Windows.Forms"
+                    HintPath = "..\..\..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Windows.Forms.dll"
+                />
+            </References>
+        </Build>
+        <Files>
+            <Include>
+                <File
+                    RelPath = "AssemblyInfo.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "DrawingTest.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+            </Include>
+        </Files>
+    </CSHARP>
+</VisualStudioProject>
+

+ 28 - 0
mcs/class/System.Drawing/Test/DrawingTest/DrawingTestHelper/DrawingTestHelper_java.vmwcsproj

@@ -0,0 +1,28 @@
+<VisualStudioProject>
+	<CSHARP ProjectType="Local" ProductVersion="7.10.3077" SchemaVersion="2.0" ProjectGuid="{8EF9FC71-4D70-4F89-BF4D-B83EF37D4A0C}" SccProjectName="SAK" SccLocalPath="..\..\..\..\.." SccProvider="MSSCCI:ClearCase">
+		<Build>
+			<Settings ApplicationIcon="" AssemblyKeyContainerName="" AssemblyName="DrawingTest" AssemblyOriginatorKeyFile="" DefaultClientScript="JScript" DefaultHTMLPageLayout="Grid" DefaultTargetSchema="IE50" DelaySign="false" OutputType="Library" PreBuildEvent="" PostBuildEvent="" RootNamespace="DrawingTest" RunPostBuildEvent="OnBuildSuccess" StartupObject="">
+				<Config Name="Debug_Java" AllowUnsafeBlocks="false" BaseAddress="285212672" CheckForOverflowUnderflow="false" ConfigurationOverrideFile="" DefineConstants="DEBUG;TRACE;TARGET_JVM" DocumentationFile="" DebugSymbols="true" FileAlignment="4096" IncrementalBuild="false" NoStdLib="false" NoWarn="1595" Optimize="false" OutputPath="..\bin\Debug_Java\" RegisterForComInterop="false" RemoveIntegerChecks="false" TreatWarningsAsErrors="false" WarningLevel="4"/>
+				<Config Name="Release_Java" AllowUnsafeBlocks="false" BaseAddress="285212672" CheckForOverflowUnderflow="false" ConfigurationOverrideFile="" DefineConstants="TRACE;JAVA" DocumentationFile="" DebugSymbols="false" FileAlignment="4096" IncrementalBuild="false" NoStdLib="false" NoWarn="1595" Optimize="true" OutputPath="..\bin\Release_Java\" RegisterForComInterop="false" RemoveIntegerChecks="false" TreatWarningsAsErrors="false" WarningLevel="4"/>
+				<Config Name="Debug" AllowUnsafeBlocks="false" BaseAddress="285212672" CheckForOverflowUnderflow="false" ConfigurationOverrideFile="" DefineConstants="DEBUG;TRACE" DocumentationFile="" DebugSymbols="true" FileAlignment="4096" IncrementalBuild="false" NoStdLib="false" NoWarn="1595" Optimize="false" OutputPath="..\bin\Debug\" RegisterForComInterop="false" RemoveIntegerChecks="false" TreatWarningsAsErrors="false" WarningLevel="4"/>
+			</Settings>
+			<References>
+				<Reference Name="System" AssemblyName="System" HintPath="..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"/>
+				<Reference Name="rt" AssemblyName="rt" HintPath="..\..\Program Files\Mainsoft\Visual MainWin for J2EE\jgac\j2sdk1.4\rt.dll" Private="False"/>
+				<Reference Name="System.Drawing" AssemblyName="System.Drawing" HintPath="C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Drawing.dll" Private="False"/>
+				<Reference Name="System.Windows.Forms" AssemblyName="System.Windows.Forms" HintPath="..\..\..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Windows.Forms.dll"/>
+				<Reference Name="Exocortex.DSP.v1.J2EE" Project="{8D602CEF-DC13-48F1-AF0C-F6201A634FD2}" Package="{83B010C7-76FC-4FAD-A26C-00D7EFE60256}"/>
+				<Reference Name="vmwutils" AssemblyName="vmwutils" HintPath="..\..\..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE\jgac\vmw4j2ee_110\vmwutils.dll" Private="False"/>
+				<Reference Name="J2SE.Helpers" AssemblyName="J2SE.Helpers" HintPath="..\..\..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE\jgac\vmw4j2ee_110\J2SE.Helpers.dll" Private="False"/>
+				<Reference Name="System.Xml" AssemblyName="System.Xml" HintPath="..\..\..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Xml.dll" Private="False"/>
+			</References>
+		</Build>
+		<Files>
+			<Include>
+				<File RelPath="AssemblyInfo.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="DrawingTest.cs" SubType="Code" BuildAction="Compile"/>
+			</Include>
+		</Files>
+		<UserProperties REFS.JarPath.j2se.helpers="..\..\..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE\jgac\vmw4j2ee_110\J2SE.Helpers.jar" REFS.JarPath.vmwutils="..\..\..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE\jgac\vmw4j2ee_110\vmwutils.jar" REFS.JarPath.system="..\..\Program Files\Mainsoft\Visual MainWin for J2EE\jgac\vmw4j2ee_110\System.jar" REFS.JarPath.rt="..\..\Program Files\Mainsoft\Visual MainWin for J2EE\j2sdk1.4\lib\rt.jar" project.JDKType="1.4.2_05" jarserver="ipa" REFS.JarPath.system.drawing="C:\Program Files\Mainsoft\Visual MainWin for J2EE\jgac\vmw4j2ee_110\System.Drawing.jar" REFS.JarPath.system.xml="..\..\..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE\jgac\vmw4j2ee_110\System.Xml.jar"/>
+	</CSHARP>
+	<VisualMainWin><Project Prop2023="1.4.2_05" Prop2024="" Prop2026="" Prop2015="" Version="1.6.0" ProjectType="1"/><References/><Configs><Config Prop2000="0" Prop2001="0" Prop2002="0" Prop2003="0" Prop2004="0" Prop2005="0" Prop2006="" Prop2007="" Prop2008="" Prop2009="" Prop2010="" Prop2011="-1" Prop2012="0" Prop2013="" Prop2014="0" Prop2016="" Prop2027="" Prop2019="0" Prop2020="285212672" Prop2021="4096" Prop2022="0" Prop2017="0" Prop2018="-1" Name="Debug_Java"/><Config Prop2000="0" Prop2001="0" Prop2002="0" Prop2003="0" Prop2004="0" Prop2005="0" Prop2006="" Prop2007="" Prop2008="" Prop2009="" Prop2010="" Prop2011="0" Prop2012="0" Prop2013="" Prop2014="0" Prop2016="" Prop2027="" Prop2019="0" Prop2020="285212672" Prop2021="4096" Prop2022="0" Prop2017="0" Prop2018="-1" Name="Release_Java"/><Config Prop2000="1" Prop2001="0" Prop2002="0" Prop2003="0" Prop2004="0" Prop2005="0" Prop2006="" Prop2007="" Prop2008="" Prop2009="" Prop2010="" Prop2011="-1" Prop2012="0" Prop2013="" Prop2014="0" Prop2016="" Prop2027="" Prop2019="0" Prop2020="285212672" Prop2021="4096" Prop2022="0" Prop2017="0" Prop2018="-1" Name="Debug"/></Configs></VisualMainWin></VisualStudioProject>

+ 10 - 0
mcs/class/System.Drawing/Test/DrawingTest/DrawingTestHelper/Makefile

@@ -0,0 +1,10 @@
+MCS=mcs
+sources=AssemblyInfo.cs DrawingTest.cs
+EXOCORTEX=Exocortex.DSP.dll
+
+DrawingTestHelper.dll: $(sources) $(EXOCORTEX)
+	$(MCS) -t:library $(sources) -r:System.Windows.Forms -r:System.Drawing -r:$(EXOCORTEX) -r:nunit.framework -out:DrawingTestHelper.dll
+
+$(EXOCORTEX):
+	cd ../Exocortex.DSP/ && make
+	cp ../Exocortex.DSP/*.dll .

+ 10 - 0
mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/Makefile

@@ -0,0 +1,10 @@
+MCS=mcs
+sources=src/AssemblyInfo.cs src/Complex.cs src/ComplexArray.cs src/ComplexF.cs src/ComplexMath.cs src/ComplexStats.cs src/Fourier.cs src/FourierDirection.cs
+
+.SUFFIXES: .cs .exe .dll
+
+all: Exocortex.DSP.dll
+
+Exocortex.DSP.dll: $(sources)
+	$(MCS) -t:library $(sources) -out:Exocortex.DSP.dll
+

+ 1124 - 0
mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/doc/Exocortex.DSP.xml

@@ -0,0 +1,1124 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>Exocortex.DSP.v1</name>
+    </assembly>
+    <members>
+        <member name="T:Exocortex.DSP.Complex">
+            <summary>
+            <p>A double-precision complex number representation.</p>
+            </summary>
+        </member>
+        <member name="F:Exocortex.DSP.Complex.Re">
+            <summary>
+            The real component of the complex number
+            </summary>
+        </member>
+        <member name="F:Exocortex.DSP.Complex.Im">
+            <summary>
+            The imaginary component of the complex number
+            </summary>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.#ctor(System.Double,System.Double)">
+            <summary>
+            Create a complex number from a real and an imaginary component
+            </summary>
+            <param name="real"></param>
+            <param name="imaginary"></param>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.#ctor(Exocortex.DSP.Complex)">
+            <summary>
+            Create a complex number based on an existing complex number
+            </summary>
+            <param name="c"></param>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.FromRealImaginary(System.Double,System.Double)">
+            <summary>
+            Create a complex number from a real and an imaginary component
+            </summary>
+            <param name="real"></param>
+            <param name="imaginary"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.FromModulusArgument(System.Double,System.Double)">
+            <summary>
+            Create a complex number from a modulus (length) and an argument (radian)
+            </summary>
+            <param name="modulus"></param>
+            <param name="argument"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.Clone">
+            <summary>
+            Clone the complex number
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.GetModulus">
+            <summary>
+            The modulus (length) of the complex number
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.GetModulusSquared">
+            <summary>
+            The squared modulus (length^2) of the complex number
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.GetArgument">
+            <summary>
+            The argument (radians) of the complex number
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.GetConjugate">
+            <summary>
+            Get the conjugate of the complex number
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.Normalize">
+            <summary>
+            Scale the complex number to 1.
+            </summary>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Explicit(Exocortex.DSP.ComplexF)~Exocortex.DSP.Complex">
+            <summary>
+            Convert to a from double precision complex number to a single precison complex number
+            </summary>
+            <param name="cF"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Explicit(System.Double)~Exocortex.DSP.Complex">
+            <summary>
+            Convert from a single precision real number to a complex number
+            </summary>
+            <param name="d"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Explicit(Exocortex.DSP.Complex)~System.Double">
+            <summary>
+            Convert from a single precision complex to a real number
+            </summary>
+            <param name="c"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Equality(Exocortex.DSP.Complex,Exocortex.DSP.Complex)">
+            <summary>
+            Are these two complex numbers equivalent?
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Inequality(Exocortex.DSP.Complex,Exocortex.DSP.Complex)">
+            <summary>
+            Are these two complex numbers different?
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.GetHashCode">
+            <summary>
+            Get the hash code of the complex number
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.Equals(System.Object)">
+            <summary>
+            Is this complex number equivalent to another object?
+            </summary>
+            <param name="o"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.CompareTo(System.Object)">
+            <summary>
+            Compare to other complex numbers or real numbers
+            </summary>
+            <param name="o"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_UnaryPlus(Exocortex.DSP.Complex)">
+            <summary>
+            This operator doesn't do much. :-)
+            </summary>
+            <param name="a"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_UnaryNegation(Exocortex.DSP.Complex)">
+            <summary>
+            Negate the complex number
+            </summary>
+            <param name="a"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Addition(Exocortex.DSP.Complex,System.Double)">
+            <summary>
+            Add a complex number to a real
+            </summary>
+            <param name="a"></param>
+            <param name="f"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Addition(System.Double,Exocortex.DSP.Complex)">
+            <summary>
+            Add a real to a complex number
+            </summary>
+            <param name="f"></param>
+            <param name="a"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Addition(Exocortex.DSP.Complex,Exocortex.DSP.Complex)">
+            <summary>
+            Add to complex numbers
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Subtraction(Exocortex.DSP.Complex,System.Double)">
+            <summary>
+            Subtract a real from a complex number
+            </summary>
+            <param name="a"></param>
+            <param name="f"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Subtraction(System.Double,Exocortex.DSP.Complex)">
+            <summary>
+            Subtract a complex number from a real
+            </summary>
+            <param name="f"></param>
+            <param name="a"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Subtraction(Exocortex.DSP.Complex,Exocortex.DSP.Complex)">
+            <summary>
+            Subtract two complex numbers
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Multiply(Exocortex.DSP.Complex,System.Double)">
+            <summary>
+            Multiply a complex number by a real
+            </summary>
+            <param name="a"></param>
+            <param name="f"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Multiply(System.Double,Exocortex.DSP.Complex)">
+            <summary>
+            Multiply a real by a complex number
+            </summary>
+            <param name="f"></param>
+            <param name="a"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Multiply(Exocortex.DSP.Complex,Exocortex.DSP.Complex)">
+            <summary>
+            Multiply two complex numbers together
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Division(Exocortex.DSP.Complex,System.Double)">
+            <summary>
+            Divide a complex number by a real number
+            </summary>
+            <param name="a"></param>
+            <param name="f"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.op_Division(Exocortex.DSP.Complex,Exocortex.DSP.Complex)">
+            <summary>
+            Divide a complex number by a complex number
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.Parse(System.String)">
+            <summary>
+            Parse a complex representation in this fashion: "( %f, %f )"
+            </summary>
+            <param name="s"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.ToString">
+            <summary>
+            Get the string representation
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.Complex.IsEqual(Exocortex.DSP.Complex,Exocortex.DSP.Complex,System.Double)">
+            <summary>
+            Determine whether two complex numbers are almost (i.e. within the tolerance) equivalent.
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+            <param name="tolerance"></param>
+            <returns></returns>
+        </member>
+        <member name="P:Exocortex.DSP.Complex.Zero">
+            <summary>
+            Represents zero
+            </summary>
+        </member>
+        <member name="P:Exocortex.DSP.Complex.I">
+            <summary>
+            Represents the result of sqrt( -1 )
+            </summary>
+        </member>
+        <member name="P:Exocortex.DSP.Complex.MaxValue">
+            <summary>
+            Represents the largest possible value of Complex.
+            </summary>
+        </member>
+        <member name="P:Exocortex.DSP.Complex.MinValue">
+            <summary>
+            Represents the smallest possible value of Complex.
+            </summary>
+        </member>
+        <member name="T:Exocortex.DSP.ComplexArray">
+            <summary>
+            <p>A set of array utilities for complex number arrays</p>
+            </summary>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.ClampLength(Exocortex.DSP.Complex[],System.Double,System.Double)">
+            <summary>
+            Clamp length (modulus) of the elements in the complex array
+            </summary>
+            <param name="array"></param>
+            <param name="fMinimum"></param>
+            <param name="fMaximum"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Clamp(Exocortex.DSP.Complex[],Exocortex.DSP.Complex,Exocortex.DSP.Complex)">
+            <summary>
+            Clamp elements in the complex array to range [minimum,maximum]
+            </summary>
+            <param name="array"></param>
+            <param name="minimum"></param>
+            <param name="maximum"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.ClampToRealUnit(Exocortex.DSP.Complex[])">
+            <summary>
+            Clamp elements in the complex array to real unit range (i.e. [0,1])
+            </summary>
+            <param name="array"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Shift(Exocortex.DSP.Complex[],System.Int32)">
+            <summary>
+            Shift (offset) the elements in the array
+            </summary>
+            <param name="array"></param>
+            <param name="offset"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Shift(Exocortex.DSP.ComplexF[],System.Int32)">
+            <summary>
+            Shift (offset) the elements in the array
+            </summary>
+            <param name="array"></param>
+            <param name="offset"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.GetLengthRange(Exocortex.DSP.Complex[],System.Double@,System.Double@)">
+            <summary>
+            Get the range of element lengths
+            </summary>
+            <param name="array"></param>
+            <param name="minimum"></param>
+            <param name="maximum"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.GetLengthRange(Exocortex.DSP.ComplexF[],System.Single@,System.Single@)">
+            <summary>
+            Get the range of element lengths
+            </summary>
+            <param name="array"></param>
+            <param name="minimum"></param>
+            <param name="maximum"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.IsEqual(Exocortex.DSP.Complex[],Exocortex.DSP.Complex[],System.Double)">
+            <summary>
+            Determine whether the elements in the two arrays are the same
+            </summary>
+            <param name="array1"></param>
+            <param name="array2"></param>
+            <param name="tolerance"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.IsEqual(Exocortex.DSP.ComplexF[],Exocortex.DSP.ComplexF[],System.Single)">
+            <summary>
+             Determine whether the elements in the two arrays are the same
+            </summary>
+            <param name="array1"></param>
+            <param name="array2"></param>
+            <param name="tolerance"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Offset(Exocortex.DSP.Complex[],System.Double)">
+            <summary>
+            Add a specific value to each element in the array
+            </summary>
+            <param name="array"></param>
+            <param name="offset"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Offset(Exocortex.DSP.Complex[],Exocortex.DSP.Complex)">
+            <summary>
+            Add a specific value to each element in the array
+            </summary>
+            <param name="array"></param>
+            <param name="offset"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Offset(Exocortex.DSP.ComplexF[],System.Single)">
+            <summary>
+            Add a specific value to each element in the array
+            </summary>
+            <param name="array"></param>
+            <param name="offset"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Offset(Exocortex.DSP.ComplexF[],Exocortex.DSP.ComplexF)">
+            <summary>
+            Add a specific value to each element in the array
+            </summary>
+            <param name="array"></param>
+            <param name="offset"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Scale(Exocortex.DSP.Complex[],System.Double)">
+            <summary>
+            Multiply each element in the array by a specific value
+            </summary>
+            <param name="array"></param>
+            <param name="scale"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Scale(Exocortex.DSP.Complex[],System.Double,System.Int32,System.Int32)">
+            <summary>
+             Multiply each element in the array by a specific value
+            </summary>
+            <param name="array"></param>
+            <param name="scale"></param>
+            <param name="start"></param>
+            <param name="length"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Scale(Exocortex.DSP.Complex[],Exocortex.DSP.Complex)">
+            <summary>
+            Multiply each element in the array by a specific value
+            </summary>
+            <param name="array"></param>
+            <param name="scale"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Scale(Exocortex.DSP.Complex[],Exocortex.DSP.Complex,System.Int32,System.Int32)">
+            <summary>
+            Multiply each element in the array by a specific value 
+            </summary>
+            <param name="array"></param>
+            <param name="scale"></param>
+            <param name="start"></param>
+            <param name="length"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Scale(Exocortex.DSP.ComplexF[],System.Single)">
+            <summary>
+            Multiply each element in the array by a specific value
+            </summary>
+            <param name="array"></param>
+            <param name="scale"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Scale(Exocortex.DSP.ComplexF[],System.Single,System.Int32,System.Int32)">
+            <summary>
+            Multiply each element in the array by a specific value 
+            </summary>
+            <param name="array"></param>
+            <param name="scale"></param>
+            <param name="start"></param>
+            <param name="length"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Scale(Exocortex.DSP.ComplexF[],Exocortex.DSP.ComplexF)">
+            <summary>
+            Multiply each element in the array by a specific value
+            </summary>
+            <param name="array"></param>
+            <param name="scale"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Scale(Exocortex.DSP.ComplexF[],Exocortex.DSP.ComplexF,System.Int32,System.Int32)">
+            <summary>
+            Multiply each element in the array by a specific value 
+            </summary>
+            <param name="array"></param>
+            <param name="scale"></param>
+            <param name="start"></param>
+            <param name="length"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Multiply(Exocortex.DSP.Complex[],Exocortex.DSP.Complex[])">
+            <summary>
+            Multiply each element in target array with corresponding element in rhs array
+            </summary>
+            <param name="target"></param>
+            <param name="rhs"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Multiply(Exocortex.DSP.Complex[],Exocortex.DSP.Complex[],Exocortex.DSP.Complex[])">
+            <summary>
+            Multiply each element in lhs array with corresponding element in rhs array and
+            put product in result array
+            </summary>
+            <param name="lhs"></param>
+            <param name="rhs"></param>
+            <param name="result"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Multiply(Exocortex.DSP.ComplexF[],Exocortex.DSP.ComplexF[])">
+            <summary>
+            Multiply each element in target array with corresponding element in rhs array
+            </summary>
+            <param name="target"></param>
+            <param name="rhs"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Multiply(Exocortex.DSP.ComplexF[],Exocortex.DSP.ComplexF[],Exocortex.DSP.ComplexF[])">
+            <summary>
+            Multiply each element in lhs array with corresponding element in rhs array and
+            put product in result array
+            </summary>
+            <param name="lhs"></param>
+            <param name="rhs"></param>
+            <param name="result"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Divide(Exocortex.DSP.Complex[],Exocortex.DSP.Complex[])">
+            <summary>
+            Divide each element in target array with corresponding element in rhs array
+            </summary>
+            <param name="target"></param>
+            <param name="rhs"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Divide(Exocortex.DSP.Complex[],Exocortex.DSP.Complex[],Exocortex.DSP.Complex[])">
+            <summary>
+            Divide each element in lhs array with corresponding element in rhs array and
+            put product in result array
+            </summary>
+            <param name="lhs"></param>
+            <param name="rhs"></param>
+            <param name="result"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Divide(Exocortex.DSP.ComplexF[],Exocortex.DSP.ComplexF[])">
+            <summary>
+            Divide each element in target array with corresponding element in rhs array
+            </summary>
+            <param name="target"></param>
+            <param name="rhs"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Divide(Exocortex.DSP.ComplexF[],Exocortex.DSP.ComplexF[],Exocortex.DSP.ComplexF[])">
+            <summary>
+            Divide each element in lhs array with corresponding element in rhs array and
+            put product in result array
+            </summary>
+            <param name="lhs"></param>
+            <param name="rhs"></param>
+            <param name="result"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Copy(Exocortex.DSP.Complex[],Exocortex.DSP.Complex[])">
+            <summary>
+            Copy an array
+            </summary>
+            <param name="dest"></param>
+            <param name="source"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Copy(Exocortex.DSP.ComplexF[],Exocortex.DSP.ComplexF[])">
+            <summary>
+            Copy an array
+            </summary>
+            <param name="dest"></param>
+            <param name="source"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Reverse(Exocortex.DSP.Complex[])">
+            <summary>
+            Reverse the elements in the array
+            </summary>
+            <param name="array"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Normalize(Exocortex.DSP.Complex[])">
+            <summary>
+            Scale and offset the elements in the array so that the
+            overall range is [0, 1]
+            </summary>
+            <param name="array"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Normalize(Exocortex.DSP.ComplexF[])">
+            <summary>
+            Scale and offset the elements in the array so that the
+            overall range is [0, 1]
+            </summary>
+            <param name="array"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Invert(Exocortex.DSP.Complex[])">
+            <summary>
+            Invert each element in the array
+            </summary>
+            <param name="array"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexArray.Invert(Exocortex.DSP.ComplexF[])">
+            <summary>
+            Invert each element in the array
+            </summary>
+            <param name="array"></param>
+        </member>
+        <member name="T:Exocortex.DSP.ComplexF">
+            <summary>
+            <p>A single-precision complex number representation.</p>
+            </summary>
+        </member>
+        <member name="F:Exocortex.DSP.ComplexF.Re">
+            <summary>
+            The real component of the complex number
+            </summary>
+        </member>
+        <member name="F:Exocortex.DSP.ComplexF.Im">
+            <summary>
+            The imaginary component of the complex number
+            </summary>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.#ctor(System.Single,System.Single)">
+            <summary>
+            Create a complex number from a real and an imaginary component
+            </summary>
+            <param name="real"></param>
+            <param name="imaginary"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.#ctor(Exocortex.DSP.ComplexF)">
+            <summary>
+            Create a complex number based on an existing complex number
+            </summary>
+            <param name="c"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.FromRealImaginary(System.Single,System.Single)">
+            <summary>
+            Create a complex number from a real and an imaginary component
+            </summary>
+            <param name="real"></param>
+            <param name="imaginary"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.FromModulusArgument(System.Single,System.Single)">
+            <summary>
+            Create a complex number from a modulus (length) and an argument (radian)
+            </summary>
+            <param name="modulus"></param>
+            <param name="argument"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.Clone">
+            <summary>
+            Clone the complex number
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.GetModulus">
+            <summary>
+            The modulus (length) of the complex number
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.GetModulusSquared">
+            <summary>
+            The squared modulus (length^2) of the complex number
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.GetArgument">
+            <summary>
+            The argument (radians) of the complex number
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.GetConjugate">
+            <summary>
+            Get the conjugate of the complex number
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.Normalize">
+            <summary>
+            Scale the complex number to 1.
+            </summary>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Explicit(Exocortex.DSP.Complex)~Exocortex.DSP.ComplexF">
+            <summary>
+            Convert to a from double precision complex number to a single precison complex number
+            </summary>
+            <param name="c"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Explicit(System.Single)~Exocortex.DSP.ComplexF">
+            <summary>
+            Convert from a single precision real number to a complex number
+            </summary>
+            <param name="f"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Explicit(Exocortex.DSP.ComplexF)~System.Single">
+            <summary>
+            Convert from a single precision complex to a real number
+            </summary>
+            <param name="c"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Equality(Exocortex.DSP.ComplexF,Exocortex.DSP.ComplexF)">
+            <summary>
+            Are these two complex numbers equivalent?
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Inequality(Exocortex.DSP.ComplexF,Exocortex.DSP.ComplexF)">
+            <summary>
+            Are these two complex numbers different?
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.GetHashCode">
+            <summary>
+            Get the hash code of the complex number
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.Equals(System.Object)">
+            <summary>
+            Is this complex number equivalent to another object?
+            </summary>
+            <param name="o"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.CompareTo(System.Object)">
+            <summary>
+            Compare to other complex numbers or real numbers
+            </summary>
+            <param name="o"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_UnaryPlus(Exocortex.DSP.ComplexF)">
+            <summary>
+            This operator doesn't do much. :-)
+            </summary>
+            <param name="a"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_UnaryNegation(Exocortex.DSP.ComplexF)">
+            <summary>
+            Negate the complex number
+            </summary>
+            <param name="a"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Addition(Exocortex.DSP.ComplexF,System.Single)">
+            <summary>
+            Add a complex number to a real
+            </summary>
+            <param name="a"></param>
+            <param name="f"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Addition(System.Single,Exocortex.DSP.ComplexF)">
+            <summary>
+            Add a real to a complex number
+            </summary>
+            <param name="f"></param>
+            <param name="a"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Addition(Exocortex.DSP.ComplexF,Exocortex.DSP.ComplexF)">
+            <summary>
+            Add to complex numbers
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Subtraction(Exocortex.DSP.ComplexF,System.Single)">
+            <summary>
+            Subtract a real from a complex number
+            </summary>
+            <param name="a"></param>
+            <param name="f"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Subtraction(System.Single,Exocortex.DSP.ComplexF)">
+            <summary>
+            Subtract a complex number from a real
+            </summary>
+            <param name="f"></param>
+            <param name="a"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Subtraction(Exocortex.DSP.ComplexF,Exocortex.DSP.ComplexF)">
+            <summary>
+            Subtract two complex numbers
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Multiply(Exocortex.DSP.ComplexF,System.Single)">
+            <summary>
+            Multiply a complex number by a real
+            </summary>
+            <param name="a"></param>
+            <param name="f"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Multiply(System.Single,Exocortex.DSP.ComplexF)">
+            <summary>
+            Multiply a real by a complex number
+            </summary>
+            <param name="f"></param>
+            <param name="a"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Multiply(Exocortex.DSP.ComplexF,Exocortex.DSP.ComplexF)">
+            <summary>
+            Multiply two complex numbers together
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Division(Exocortex.DSP.ComplexF,System.Single)">
+            <summary>
+            Divide a complex number by a real number
+            </summary>
+            <param name="a"></param>
+            <param name="f"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.op_Division(Exocortex.DSP.ComplexF,Exocortex.DSP.ComplexF)">
+            <summary>
+            Divide a complex number by a complex number
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.Parse(System.String)">
+            <summary>
+            Parse a complex representation in this fashion: "( %f, %f )"
+            </summary>
+            <param name="s"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.ToString">
+            <summary>
+            Get the string representation
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexF.IsEqual(Exocortex.DSP.ComplexF,Exocortex.DSP.ComplexF,System.Single)">
+            <summary>
+            Determine whether two complex numbers are almost (i.e. within the tolerance) equivalent.
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+            <param name="tolerance"></param>
+            <returns></returns>
+        </member>
+        <member name="P:Exocortex.DSP.ComplexF.Zero">
+            <summary>
+            Represents zero
+            </summary>
+        </member>
+        <member name="P:Exocortex.DSP.ComplexF.I">
+            <summary>
+            Represents the result of sqrt( -1 )
+            </summary>
+        </member>
+        <member name="P:Exocortex.DSP.ComplexF.MaxValue">
+            <summary>
+            Represents the largest possible value of ComplexF.
+            </summary>
+        </member>
+        <member name="P:Exocortex.DSP.ComplexF.MinValue">
+            <summary>
+            Represents the smallest possible value of ComplexF.
+            </summary>
+        </member>
+        <member name="T:Exocortex.DSP.ComplexMath">
+            <summary>
+            <p>Various mathematical functions for complex numbers.</p>
+            </summary>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexMath.Swap(Exocortex.DSP.Complex@,Exocortex.DSP.Complex@)">
+            <summary>
+            Swap two complex numbers
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexMath.Swap(Exocortex.DSP.ComplexF@,Exocortex.DSP.ComplexF@)">
+            <summary>
+            Swap two complex numbers
+            </summary>
+            <param name="a"></param>
+            <param name="b"></param>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexMath.Sqrt(Exocortex.DSP.ComplexF)">
+            <summary>
+            Calculate the square root of a complex number
+            </summary>
+            <param name="c"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexMath.Sqrt(Exocortex.DSP.Complex)">
+            <summary>
+            Calculate the square root of a complex number
+            </summary>
+            <param name="c"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexMath.Pow(Exocortex.DSP.ComplexF,System.Double)">
+            <summary>
+            Calculate the power of a complex number
+            </summary>
+            <param name="c"></param>
+            <param name="exponent"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexMath.Pow(Exocortex.DSP.Complex,System.Double)">
+            <summary>
+            Calculate the power of a complex number
+            </summary>
+            <param name="c"></param>
+            <param name="exponent"></param>
+            <returns></returns>
+        </member>
+        <member name="T:Exocortex.DSP.ComplexStats">
+            <summary>
+            <p>A set of statistical utilities for complex number arrays</p>
+            </summary>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexStats.Sum(Exocortex.DSP.ComplexF[])">
+            <summary>
+            Calculate the sum
+            </summary>
+            <param name="data"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexStats.Sum(Exocortex.DSP.Complex[])">
+            <summary>
+            Calculate the sum
+            </summary>
+            <param name="data"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexStats.SumOfSquares(Exocortex.DSP.ComplexF[])">
+            <summary>
+            Calculate the sum of squares
+            </summary>
+            <param name="data"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexStats.SumOfSquares(Exocortex.DSP.Complex[])">
+            <summary>
+            Calculate the sum of squares
+            </summary>
+            <param name="data"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexStats.Mean(Exocortex.DSP.ComplexF[])">
+            <summary>
+            Calculate the mean (average)
+            </summary>
+            <param name="data"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexStats.Mean(Exocortex.DSP.Complex[])">
+            <summary>
+            Calculate the mean (average)
+            </summary>
+            <param name="data"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexStats.Variance(Exocortex.DSP.ComplexF[])">
+            <summary>
+            Calculate the variance
+            </summary>
+            <param name="data"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexStats.Variance(Exocortex.DSP.Complex[])">
+            <summary>
+            Calculate the variance 
+            </summary>
+            <param name="data"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexStats.StdDev(Exocortex.DSP.ComplexF[])">
+            <summary>
+            Calculate the standard deviation
+            </summary>
+            <param name="data"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexStats.StdDev(Exocortex.DSP.Complex[])">
+            <summary>
+            Calculate the standard deviation 
+            </summary>
+            <param name="data"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexStats.RMSError(Exocortex.DSP.ComplexF[],Exocortex.DSP.ComplexF[])">
+            <summary>
+            Calculate the root mean squared (RMS) error between two sets of data.
+            </summary>
+            <param name="alpha"></param>
+            <param name="beta"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Exocortex.DSP.ComplexStats.RMSError(Exocortex.DSP.Complex[],Exocortex.DSP.Complex[])">
+            <summary>
+            Calculate the root mean squared (RMS) error between two sets of data.
+            </summary>
+            <param name="alpha"></param>
+            <param name="beta"></param>
+            <returns></returns>
+        </member>
+        <member name="T:Exocortex.DSP.Fourier">
+            <summary>
+            <p>Static functions for doing various Fourier Operations.</p>
+            </summary>
+        </member>
+        <member name="M:Exocortex.DSP.Fourier.FFT(System.Single[],System.Int32,Exocortex.DSP.FourierDirection)">
+            <summary>
+            Compute a 1D fast Fourier transform of a dataset of complex numbers (as pairs of float's).
+            </summary>
+            <param name="data"></param>
+            <param name="length"></param>
+            <param name="direction"></param>
+        </member>
+        <member name="M:Exocortex.DSP.Fourier.FFT_Quick(System.Single[],System.Int32,Exocortex.DSP.FourierDirection)">
+            <summary>
+            Compute a 1D fast Fourier transform of a dataset of complex numbers (as pairs of float's).
+            </summary>
+            <param name="data"></param>
+            <param name="length"></param>
+            <param name="direction"></param>
+        </member>
+        <member name="M:Exocortex.DSP.Fourier.FFT(Exocortex.DSP.ComplexF[],System.Int32,Exocortex.DSP.FourierDirection)">
+            <summary>
+            Compute a 1D fast Fourier transform of a dataset of complex numbers.
+            </summary>
+            <param name="data"></param>
+            <param name="length"></param>
+            <param name="direction"></param>
+        </member>
+        <member name="M:Exocortex.DSP.Fourier.FFT_Quick(Exocortex.DSP.ComplexF[],System.Int32,Exocortex.DSP.FourierDirection)">
+            <summary>
+            Compute a 1D fast Fourier transform of a dataset of complex numbers.
+            </summary>
+            <param name="data"></param>
+            <param name="length"></param>
+            <param name="direction"></param>
+        </member>
+        <member name="M:Exocortex.DSP.Fourier.FFT(Exocortex.DSP.ComplexF[],Exocortex.DSP.FourierDirection)">
+            <summary>
+            Compute a 1D fast Fourier transform of a dataset of complex numbers.
+            </summary>
+            <param name="data"></param>
+            <param name="direction"></param>
+        </member>
+        <member name="M:Exocortex.DSP.Fourier.FFT(Exocortex.DSP.Complex[],System.Int32,Exocortex.DSP.FourierDirection)">
+            <summary>
+            Compute a 1D fast Fourier transform of a dataset of complex numbers.
+            </summary>
+            <param name="data"></param>
+            <param name="length"></param>
+            <param name="direction"></param>
+        </member>
+        <member name="M:Exocortex.DSP.Fourier.FFT_Quick(Exocortex.DSP.Complex[],System.Int32,Exocortex.DSP.FourierDirection)">
+            <summary>
+            Compute a 1D fast Fourier transform of a dataset of complex numbers.
+            </summary>
+            <param name="data"></param>
+            <param name="length"></param>
+            <param name="direction"></param>
+        </member>
+        <member name="M:Exocortex.DSP.Fourier.RFFT(System.Single[],Exocortex.DSP.FourierDirection)">
+            <summary>
+            Compute a 1D real-symmetric fast fourier transform.
+            </summary>
+            <param name="data"></param>
+            <param name="direction"></param>
+        </member>
+        <member name="M:Exocortex.DSP.Fourier.RFFT(System.Single[],System.Int32,Exocortex.DSP.FourierDirection)">
+            <summary>
+            Compute a 1D real-symmetric fast fourier transform.
+            </summary>
+            <param name="data"></param>
+            <param name="length"></param>
+            <param name="direction"></param>
+        </member>
+        <member name="M:Exocortex.DSP.Fourier.FFT2(System.Single[],System.Int32,System.Int32,Exocortex.DSP.FourierDirection)">
+            <summary>
+            Compute a 2D fast fourier transform on a data set of complex numbers (represented as pairs of floats)
+            </summary>
+            <param name="data"></param>
+            <param name="xLength"></param>
+            <param name="yLength"></param>
+            <param name="direction"></param>
+        </member>
+        <member name="M:Exocortex.DSP.Fourier.FFT2(Exocortex.DSP.ComplexF[],System.Int32,System.Int32,Exocortex.DSP.FourierDirection)">
+            <summary>
+            Compute a 2D fast fourier transform on a data set of complex numbers
+            </summary>
+            <param name="data"></param>
+            <param name="xLength"></param>
+            <param name="yLength"></param>
+            <param name="direction"></param>
+        </member>
+        <member name="M:Exocortex.DSP.Fourier.FFT2(Exocortex.DSP.Complex[],System.Int32,System.Int32,Exocortex.DSP.FourierDirection)">
+            <summary>
+            Compute a 2D fast fourier transform on a data set of complex numbers
+            </summary>
+            <param name="data"></param>
+            <param name="xLength"></param>
+            <param name="yLength"></param>
+            <param name="direction"></param>
+        </member>
+        <member name="M:Exocortex.DSP.Fourier.FFT3(Exocortex.DSP.ComplexF[],System.Int32,System.Int32,System.Int32,Exocortex.DSP.FourierDirection)">
+            <summary>
+            Compute a 3D fast fourier transform on a data set of complex numbers
+            </summary>
+            <param name="data"></param>
+            <param name="xLength"></param>
+            <param name="yLength"></param>
+            <param name="zLength"></param>
+            <param name="direction"></param>
+        </member>
+        <member name="M:Exocortex.DSP.Fourier.FFT3(Exocortex.DSP.Complex[],System.Int32,System.Int32,System.Int32,Exocortex.DSP.FourierDirection)">
+            <summary>
+            Compute a 3D fast fourier transform on a data set of complex numbers
+            </summary>
+            <param name="data"></param>
+            <param name="xLength"></param>
+            <param name="yLength"></param>
+            <param name="zLength"></param>
+            <param name="direction"></param>
+        </member>
+        <member name="T:Exocortex.DSP.FourierDirection">
+            <summary>
+            <p>The direction of the fourier transform.</p>
+            </summary>
+        </member>
+        <member name="F:Exocortex.DSP.FourierDirection.Forward">
+            <summary>
+            Forward direction.  Usually in reference to moving from temporal
+            representation to frequency representation
+            </summary>
+        </member>
+        <member name="F:Exocortex.DSP.FourierDirection.Backward">
+            <summary>
+            Backward direction. Usually in reference to moving from frequency
+            representation to temporal representation
+            </summary>
+        </member>
+    </members>
+</doc>

+ 58 - 0
mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/AssemblyInfo.cs

@@ -0,0 +1,58 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]		
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the 
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing. 
+//
+// Notes: 
+//   (*) If no key is specified, the assembly is not signed.
+//   (*) KeyName refers to a key that has been installed in the Crypto Service
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains
+//       a key.
+//   (*) If the KeyFile and the KeyName values are both specified, the 
+//       following processing occurs:
+//       (1) If the KeyName can be found in the CSP, that key is used.
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key 
+//           in the KeyFile is installed into the CSP and used.
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+//       When specifying the KeyFile, the location of the KeyFile should be
+//       relative to the project output directory which is
+//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+//       located in the project directory, you would specify the AssemblyKeyFile 
+//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+//       documentation for more information on this.
+//
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]

+ 527 - 0
mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/Complex.cs

@@ -0,0 +1,527 @@
+/*
+ * BSD Licence:
+ * Copyright (c) 2001, 2002 Ben Houston [ [email protected] ]
+ * Exocortex Technologies [ www.exocortex.org ]
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ * notice, this list of conditions and the following disclaimer in the 
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+
+namespace Exocortex.DSP {
+
+	// Comments? Questions? Bugs? Tell Ben Houston at [email protected]
+	// Version: May 4, 2002
+
+	/// <summary>
+	/// <p>A double-precision complex number representation.</p>
+	/// </summary>
+	[StructLayout(LayoutKind.Sequential)]
+	public struct Complex : IComparable, ICloneable {
+
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// The real component of the complex number
+		/// </summary>
+		public double Re;
+
+		/// <summary>
+		/// The imaginary component of the complex number
+		/// </summary>
+		public double Im;
+
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Create a complex number from a real and an imaginary component
+		/// </summary>
+		/// <param name="real"></param>
+		/// <param name="imaginary"></param>
+		public Complex( double real, double imaginary ) {
+			this.Re		= (double) real;
+			this.Im	= (double) imaginary;
+		}
+
+		/// <summary>
+		/// Create a complex number based on an existing complex number
+		/// </summary>
+		/// <param name="c"></param>
+		public Complex( Complex c ) {
+			this.Re		= c.Re;
+			this.Im	= c.Im;
+		}
+
+		/// <summary>
+		/// Create a complex number from a real and an imaginary component
+		/// </summary>
+		/// <param name="real"></param>
+		/// <param name="imaginary"></param>
+		/// <returns></returns>
+		static public Complex	FromRealImaginary( double real, double imaginary ) {
+			Complex c;
+			c.Re		= (double) real;
+			c.Im = (double) imaginary;
+			return c;
+		}
+
+		/// <summary>
+		/// Create a complex number from a modulus (length) and an argument (radian)
+		/// </summary>
+		/// <param name="modulus"></param>
+		/// <param name="argument"></param>
+		/// <returns></returns>
+		static public Complex	FromModulusArgument( double modulus, double argument ) {
+			Complex c;
+			c.Re		= (double)( modulus * System.Math.Cos( argument ) );
+			c.Im	= (double)( modulus * System.Math.Sin( argument ) );
+			return c;
+		}
+		
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		object	ICloneable.Clone() {
+			return	new Complex( this );
+		}
+		/// <summary>
+		/// Clone the complex number
+		/// </summary>
+		/// <returns></returns>
+		public Complex	Clone() {
+			return	new Complex( this );
+		}
+		
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// The modulus (length) of the complex number
+		/// </summary>
+		/// <returns></returns>
+		public double	GetModulus() {
+			double	x	= this.Re;
+			double	y	= this.Im;
+			return	(double) Math.Sqrt( x*x + y*y );
+		}
+
+		/// <summary>
+		/// The squared modulus (length^2) of the complex number
+		/// </summary>
+		/// <returns></returns>
+		public double	GetModulusSquared() {
+			double	x	= this.Re;
+			double	y	= this.Im;
+			return	(double) x*x + y*y;
+		}
+
+		/// <summary>
+		/// The argument (radians) of the complex number
+		/// </summary>
+		/// <returns></returns>
+		public double	GetArgument() {
+			return (double) Math.Atan2( this.Im, this.Re );
+		}
+
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Get the conjugate of the complex number
+		/// </summary>
+		/// <returns></returns>
+		public Complex GetConjugate() {
+			return FromRealImaginary( this.Re, -this.Im );
+		}
+
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Scale the complex number to 1.
+		/// </summary>
+		public void Normalize() {
+			double	modulus = this.GetModulus();
+			if( modulus == 0 ) {
+				throw new DivideByZeroException( "Can not normalize a complex number that is zero." );
+			}
+			this.Re	= (double)( this.Re / modulus );
+			this.Im	= (double)( this.Im / modulus );
+		}
+
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Convert to a from double precision complex number to a single precison complex number
+		/// </summary>
+		/// <param name="cF"></param>
+		/// <returns></returns>
+		public static explicit operator Complex ( ComplexF cF ) {
+			Complex c;
+			c.Re	= (double) cF.Re;
+			c.Im	= (double) cF.Im;
+			return c;
+		}
+		
+		/// <summary>
+		/// Convert from a single precision real number to a complex number
+		/// </summary>
+		/// <param name="d"></param>
+		/// <returns></returns>
+		public static explicit operator Complex ( double d ) {
+			Complex c;
+			c.Re	= (double) d;
+			c.Im	= (double) 0;
+			return c;
+		}
+
+		/// <summary>
+		/// Convert from a single precision complex to a real number
+		/// </summary>
+		/// <param name="c"></param>
+		/// <returns></returns>
+		public static explicit operator double ( Complex c ) {
+			return (double) c.Re;
+		}
+		
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Are these two complex numbers equivalent?
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		/// <returns></returns>
+		public static bool	operator==( Complex a, Complex b ) {
+			return	( a.Re == b.Re ) && ( a.Im == b.Im );
+		}
+
+		/// <summary>
+		/// Are these two complex numbers different?
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		/// <returns></returns>
+		public static bool	operator!=( Complex a, Complex b ) {
+			return	( a.Re != b.Re ) || ( a.Im != b.Im );
+		}
+
+		/// <summary>
+		/// Get the hash code of the complex number
+		/// </summary>
+		/// <returns></returns>
+		public override int		GetHashCode() {
+			return	( this.Re.GetHashCode() ^ this.Im.GetHashCode() );
+		}
+
+		/// <summary>
+		/// Is this complex number equivalent to another object?
+		/// </summary>
+		/// <param name="o"></param>
+		/// <returns></returns>
+		public override bool	Equals( object o ) {
+			if( o is Complex ) {
+				Complex c = (Complex) o;
+				return   ( this == c );
+			}
+			return	false;
+		}
+
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Compare to other complex numbers or real numbers
+		/// </summary>
+		/// <param name="o"></param>
+		/// <returns></returns>
+		public int	CompareTo( object o ) {
+			if( o == null ) {
+				return 1;  // null sorts before current
+			}
+			if( o is Complex ) {
+				return	this.GetModulus().CompareTo( ((Complex)o).GetModulus() );
+			}
+			if( o is double ) {
+				return	this.GetModulus().CompareTo( (double)o );
+			}
+			if( o is ComplexF ) {
+				return	this.GetModulus().CompareTo( ((ComplexF)o).GetModulus() );
+			}
+			if( o is float ) {
+				return	this.GetModulus().CompareTo( (float)o );
+			}
+			throw new ArgumentException();
+		}
+
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// This operator doesn't do much. :-)
+		/// </summary>
+		/// <param name="a"></param>
+		/// <returns></returns>
+		public static Complex operator+( Complex a ) {
+			return a;
+		}
+
+		/// <summary>
+		/// Negate the complex number
+		/// </summary>
+		/// <param name="a"></param>
+		/// <returns></returns>
+		public static Complex operator-( Complex a ) {
+			a.Re	= -a.Re;
+			a.Im	= -a.Im;
+			return a;
+		}
+
+		/// <summary>
+		/// Add a complex number to a real
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="f"></param>
+		/// <returns></returns>
+		public static Complex operator+( Complex a, double f ) {
+			a.Re	= (double)( a.Re + f );
+			return a;
+		}
+
+		/// <summary>
+		/// Add a real to a complex number
+		/// </summary>
+		/// <param name="f"></param>
+		/// <param name="a"></param>
+		/// <returns></returns>
+		public static Complex operator+( double f, Complex a ) {
+			a.Re	= (double)( a.Re + f );
+			return a;
+		}
+
+		/// <summary>
+		/// Add to complex numbers
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		/// <returns></returns>
+		public static Complex operator+( Complex a, Complex b ) {
+			a.Re	= a.Re + b.Re;
+			a.Im	= a.Im + b.Im;
+			return a;
+		}
+
+		/// <summary>
+		/// Subtract a real from a complex number
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="f"></param>
+		/// <returns></returns>
+		public static Complex operator-( Complex a, double f ) {
+			a.Re	= (double)( a.Re - f );
+			return a;
+		}
+
+		/// <summary>
+		/// Subtract a complex number from a real
+		/// </summary>
+		/// <param name="f"></param>
+		/// <param name="a"></param>
+		/// <returns></returns>
+		public static Complex operator-( double f, Complex a ) {
+			a.Re	= (float)( f - a.Re );
+			a.Im	= (float)( 0 - a.Im );
+			return a;
+		}
+
+		/// <summary>
+		/// Subtract two complex numbers
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		/// <returns></returns>
+		public static Complex operator-( Complex a, Complex b ) {
+			a.Re	= a.Re - b.Re;
+			a.Im	= a.Im - b.Im;
+			return a;
+		}
+
+		/// <summary>
+		/// Multiply a complex number by a real
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="f"></param>
+		/// <returns></returns>
+		public static Complex operator*( Complex a, double f ) {
+			a.Re	= (double)( a.Re * f );
+			a.Im	= (double)( a.Im * f );
+			return a;
+		}
+		
+		/// <summary>
+		/// Multiply a real by a complex number
+		/// </summary>
+		/// <param name="f"></param>
+		/// <param name="a"></param>
+		/// <returns></returns>
+		public static Complex operator*( double f, Complex a ) {
+			a.Re	= (double)( a.Re * f );
+			a.Im	= (double)( a.Im * f );
+			
+			return a;
+		}
+		
+		/// <summary>
+		/// Multiply two complex numbers together
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		/// <returns></returns>
+		public static Complex operator*( Complex a, Complex b ) {
+			// (x + yi)(u + vi) = (xu – yv) + (xv + yu)i. 
+			double	x = a.Re, y = a.Im;
+			double	u = b.Re, v = b.Im;
+			
+			a.Re	= (double)( x*u - y*v );
+			a.Im	= (double)( x*v + y*u );
+			
+			return a;
+		}
+
+		/// <summary>
+		/// Divide a complex number by a real number
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="f"></param>
+		/// <returns></returns>
+		public static Complex operator/( Complex a, double f ) {
+			if( f == 0 ) {
+				throw new DivideByZeroException();
+			}
+			
+			a.Re	= (double)( a.Re / f );
+			a.Im	= (double)( a.Im / f );
+			
+			return a;
+		}
+		
+		/// <summary>
+		/// Divide a complex number by a complex number
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		/// <returns></returns>
+		public static Complex operator/( Complex a, Complex b ) {
+			double	x = a.Re,	y = a.Im;
+			double	u = b.Re,	v = b.Im;
+			double	denom = u*u + v*v;
+
+			if( denom == 0 ) {
+				throw new DivideByZeroException();
+			}
+
+			a.Re	= (double)( ( x*u + y*v ) / denom );
+			a.Im	= (double)( ( y*u - x*v ) / denom );
+			
+			return a;
+		}
+
+		/// <summary>
+		/// Parse a complex representation in this fashion: "( %f, %f )"
+		/// </summary>
+		/// <param name="s"></param>
+		/// <returns></returns>
+		static public Complex Parse( string s ) {
+			throw new NotImplementedException( "Complex Complex.Parse( string s ) is not implemented." );
+		}
+		
+		/// <summary>
+		/// Get the string representation
+		/// </summary>
+		/// <returns></returns>
+		public override string ToString() {
+			return	String.Format( "( {0}, {1}i )", this.Re, this.Im );
+		}
+
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Determine whether two complex numbers are almost (i.e. within the tolerance) equivalent.
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		/// <param name="tolerance"></param>
+		/// <returns></returns>
+		static public bool IsEqual( Complex a, Complex b, double tolerance ) {
+			return
+				( Math.Abs( a.Re - b.Re ) < tolerance ) &&
+				( Math.Abs( a.Im - b.Im ) < tolerance );
+
+		}
+		
+		//----------------------------------------------------------------------------------
+		//----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Represents zero
+		/// </summary>
+		static public Complex	Zero {
+			get	{	return	new Complex( 0, 0 );	}
+		}
+
+		/// <summary>
+		/// Represents the result of sqrt( -1 )
+		/// </summary>
+		static public Complex	I {
+			get {	return	new Complex( 0, 1 );	}
+		}
+
+		/// <summary>
+		/// Represents the largest possible value of Complex.
+		/// </summary>
+		static public Complex	MaxValue {
+			get {	return	new Complex( double.MaxValue, double.MaxValue );	}
+		}
+
+		/// <summary>
+		/// Represents the smallest possible value of Complex.
+		/// </summary>
+		static public Complex	MinValue {
+			get {	return	new Complex( double.MinValue, double.MinValue );	}
+		}
+
+
+		//----------------------------------------------------------------------------------
+		//----------------------------------------------------------------------------------
+	}
+
+}

+ 682 - 0
mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/ComplexArray.cs

@@ -0,0 +1,682 @@
+/*
+ * BSD Licence:
+ * Copyright (c) 2001, 2002 Ben Houston [ [email protected] ]
+ * Exocortex Technologies [ www.exocortex.org ]
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ * notice, this list of conditions and the following disclaimer in the 
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+
+using System;
+using System.Diagnostics;
+using Exocortex.DSP;
+
+namespace Exocortex.DSP {
+	
+	// Comments? Questions? Bugs? Tell Ben Houston at [email protected]
+	// Version: May 4, 2002
+	
+	/// <summary>
+	/// <p>A set of array utilities for complex number arrays</p>
+	/// </summary>
+	public class ComplexArray {
+
+		//---------------------------------------------------------------------------------------------
+
+		private ComplexArray() {
+		}
+
+		//---------------------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Clamp length (modulus) of the elements in the complex array
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="fMinimum"></param>
+		/// <param name="fMaximum"></param>
+		static public void ClampLength( Complex[] array, double fMinimum, double fMaximum ) {
+			for( int i = 0; i < array.Length; i ++ ) {
+				array[i] = Complex.FromModulusArgument( Math.Max( fMinimum, Math.Min( fMaximum, array[i].GetModulus() ) ), array[i].GetArgument() );
+			}
+		}
+
+		/// <summary>
+		/// Clamp elements in the complex array to range [minimum,maximum]
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="minimum"></param>
+		/// <param name="maximum"></param>
+		static public void Clamp( Complex[] array, Complex minimum, Complex maximum ) {
+			for( int i = 0; i < array.Length; i ++ ) {
+				array[i].Re	= Math.Min( Math.Max( array[ i ].Re, minimum.Re ), maximum.Re );
+				array[i].Im	= Math.Min( Math.Max( array[ i ].Re, minimum.Im ), maximum.Im );
+			}
+		}
+
+		/// <summary>
+		/// Clamp elements in the complex array to real unit range (i.e. [0,1])
+		/// </summary>
+		/// <param name="array"></param>
+		static public void ClampToRealUnit( Complex[] array ) {
+			for( int i = 0; i < array.Length; i ++ ) {
+				array[i].Re =  Math.Min( Math.Max( array[i].Re, 0 ), 1 );
+				array[i].Im = 0;
+			}
+		}
+		
+		//---------------------------------------------------------------------------------------------
+
+		static private bool			_workspaceFLocked	= false;
+		static private ComplexF[]	_workspaceF			= new ComplexF[ 0 ];
+
+		static private void		LockWorkspaceF( int length, ref ComplexF[] workspace ) {
+			Debug.Assert( _workspaceFLocked == false );
+			_workspaceFLocked = true;
+			if( length >= _workspaceF.Length ) {
+				_workspaceF	= new ComplexF[ length ];
+			}
+			workspace =	_workspaceF;
+		}
+		static private void		UnlockWorkspaceF( ref ComplexF[] workspace ) {
+			Debug.Assert( _workspaceF == workspace );
+			Debug.Assert( _workspaceFLocked == true );
+			_workspaceFLocked = false;
+			workspace = null;
+		}
+
+		//---------------------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Shift (offset) the elements in the array
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="offset"></param>
+		static public void Shift( Complex[] array, int offset ) {
+			Debug.Assert( array != null );
+			Debug.Assert( offset >= 0 );
+			Debug.Assert( offset < array.Length );
+
+			if( offset == 0 ) {
+				return;
+			}
+
+			int			length	= array.Length;
+			Complex[]	temp	= new Complex[ length ];
+
+			for( int i = 0; i < length; i ++ ) {
+				temp[ ( i + offset ) % length ] = array[ i ];
+			}
+			for( int i = 0; i < length; i ++ ) {
+				array[ i ] = temp[ i ];
+			}
+		}
+
+		/// <summary>
+		/// Shift (offset) the elements in the array
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="offset"></param>
+		static public void Shift( ComplexF[] array, int offset ) {
+			Debug.Assert( array != null );
+			Debug.Assert( offset >= 0 );
+			Debug.Assert( offset < array.Length );
+
+			if( offset == 0 ) {
+				return;
+			}
+
+			int			length		= array.Length;
+			ComplexF[]	workspace	= null;
+			ComplexArray.LockWorkspaceF( length, ref workspace );
+
+			for( int i = 0; i < length; i ++ ) {
+				workspace[ ( i + offset ) % length ] = array[ i ];
+			}
+			for( int i = 0; i < length; i ++ ) {
+				array[ i ] = workspace[ i ];
+			}
+
+			ComplexArray.UnlockWorkspaceF( ref workspace );
+		}
+
+		//---------------------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Get the range of element lengths
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="minimum"></param>
+		/// <param name="maximum"></param>
+		static public void GetLengthRange( Complex[] array, ref double minimum, ref double maximum ) {
+			minimum = +double.MaxValue;
+			maximum = -double.MaxValue;
+			for( int i = 0; i < array.Length; i ++ ) {
+				double temp = array[i].GetModulus();
+				minimum = Math.Min( temp, minimum );
+				maximum = Math.Max( temp, maximum );
+			}
+		}
+		/// <summary>
+		/// Get the range of element lengths
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="minimum"></param>
+		/// <param name="maximum"></param>
+		static public void GetLengthRange( ComplexF[] array, ref float minimum, ref float maximum ) {
+			minimum = +float.MaxValue;
+			maximum = -float.MaxValue;
+			for( int i = 0; i < array.Length; i ++ ) {
+				float temp = array[i].GetModulus();
+				minimum = Math.Min( temp, minimum );
+				maximum = Math.Max( temp, maximum );
+			}
+		}
+
+		// // <summary>
+		// // Conver the complex array to a double array
+		// // </summary>
+		// // <param name="array"></param>
+		// // <param name="style"></param>
+		// // <returns></returns>
+		/* static public double[]	ConvertToDoubleArray( Complex[] array, ConversionStyle style ) {
+			double[] newArray = new double[ array.Length ];
+			switch( style ) {
+			case ConversionStyle.Length:
+				for( int i = 0; i < array.Length; i ++ ) {
+					newArray[i] = (double) array[i].GetModulus();
+				}
+				break;
+			case ConversionStyle.Real:
+				for( int i = 0; i < array.Length; i ++ ) {
+					newArray[i] = (double) array[i].Re;
+				}
+				break;
+			case ConversionStyle.Imaginary:
+				for( int i = 0; i < array.Length; i ++ ) {
+					newArray[i] = (double) array[i].Im;
+				}
+				break;
+			default:
+				Debug.Assert( false );
+				break;
+			}
+			return	newArray;
+		}	 */
+
+		//---------------------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Determine whether the elements in the two arrays are the same
+		/// </summary>
+		/// <param name="array1"></param>
+		/// <param name="array2"></param>
+		/// <param name="tolerance"></param>
+		/// <returns></returns>
+		static public bool		IsEqual( Complex[] array1, Complex[] array2, double tolerance ) {
+			if ( array1.Length != array2.Length ) {
+				return false;
+			}
+			for( int i = 0; i < array1.Length; i ++ ) {
+				if( Complex.IsEqual( array1[i], array2[i], tolerance ) == false ) {
+					return false;
+				}
+			}
+			return true;
+		}
+
+		/// <summary>
+		///  Determine whether the elements in the two arrays are the same
+		/// </summary>
+		/// <param name="array1"></param>
+		/// <param name="array2"></param>
+		/// <param name="tolerance"></param>
+		/// <returns></returns>
+		static public bool		IsEqual( ComplexF[] array1, ComplexF[] array2, float tolerance ) {
+			if ( array1.Length != array2.Length ) {
+				return false;
+			}
+			for( int i = 0; i < array1.Length; i ++ ) {
+				if( ComplexF.IsEqual( array1[i], array2[i], tolerance ) == false ) {
+					return false;
+				}
+			}
+			return true;
+		}
+
+		//---------------------------------------------------------------------------------------------
+		
+		/// <summary>
+		/// Add a specific value to each element in the array
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="offset"></param>
+		static public void Offset( Complex[] array, double offset ) {
+			int length = array.Length;
+			for( int i = 0; i < length; i ++ ) {
+				array[i].Re += offset;
+			}
+		}
+
+		/// <summary>
+		/// Add a specific value to each element in the array
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="offset"></param>
+		static public void Offset( Complex[] array, Complex offset ) {
+			int length = array.Length;
+			for( int i = 0; i < length; i ++ ) {
+				array[i] += offset;
+			}
+		}
+
+		/// <summary>
+		/// Add a specific value to each element in the array
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="offset"></param>
+		static public void Offset( ComplexF[] array, float offset ) {
+			int length = array.Length;
+			for( int i = 0; i < length; i ++ ) {
+				array[i].Re += offset;
+			}
+		}
+
+		/// <summary>
+		/// Add a specific value to each element in the array
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="offset"></param>
+		static public void Offset( ComplexF[] array, ComplexF offset ) {
+			int length = array.Length;
+			for( int i = 0; i < length; i ++ ) {
+				array[i] += offset;
+			}
+		}
+
+		//---------------------------------------------------------------------------------------------
+		
+		/// <summary>
+		/// Multiply each element in the array by a specific value
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="scale"></param>
+		static public void Scale( Complex[] array, double scale ) {
+			Debug.Assert( array != null );
+
+			int length = array.Length;
+			for( int i = 0; i < length; i ++ ) {
+				array[i] *= scale;
+			}
+		}
+		/// <summary>
+		///  Multiply each element in the array by a specific value
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="scale"></param>
+		/// <param name="start"></param>
+		/// <param name="length"></param>
+		static public void Scale( Complex[] array, double scale, int start, int length ) {
+			Debug.Assert( array != null );
+			Debug.Assert( start >= 0 );
+			Debug.Assert( length >= 0 );
+			Debug.Assert( ( start + length ) < array.Length );
+
+			for( int i = 0; i < length; i ++ ) {
+				array[i + start] *= scale;
+			}
+		}
+
+		/// <summary>
+		/// Multiply each element in the array by a specific value
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="scale"></param>
+		static public void Scale( Complex[] array, Complex scale ) {
+			Debug.Assert( array != null );
+
+			int length = array.Length;
+			for( int i = 0; i < length; i ++ ) {
+				array[i] *= scale;
+			}
+		}
+		/// <summary>
+		/// Multiply each element in the array by a specific value 
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="scale"></param>
+		/// <param name="start"></param>
+		/// <param name="length"></param>
+		static public void Scale( Complex[] array, Complex scale, int start, int length ) {
+			Debug.Assert( array != null );
+			Debug.Assert( start >= 0 );
+			Debug.Assert( length >= 0 );
+			Debug.Assert( ( start + length ) < array.Length );
+
+			for( int i = 0; i < length; i ++ ) {
+				array[i + start] *= scale;
+			}
+		}
+
+		/// <summary>
+		/// Multiply each element in the array by a specific value
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="scale"></param>
+		static public void Scale( ComplexF[] array, float scale ) {
+			Debug.Assert( array != null );
+
+			int length = array.Length;
+			for( int i = 0; i < length; i ++ ) {
+				array[i] *= scale;
+			}
+		}
+		/// <summary>
+		/// Multiply each element in the array by a specific value 
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="scale"></param>
+		/// <param name="start"></param>
+		/// <param name="length"></param>
+		static public void Scale( ComplexF[] array, float scale, int start, int length ) {
+			Debug.Assert( array != null );
+			Debug.Assert( start >= 0 );
+			Debug.Assert( length >= 0 );
+			Debug.Assert( ( start + length ) < array.Length );
+
+			for( int i = 0; i < length; i ++ ) {
+				array[i + start] *= scale;
+			}
+		}
+
+		/// <summary>
+		/// Multiply each element in the array by a specific value
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="scale"></param>
+		static public void Scale( ComplexF[] array, ComplexF scale ) {
+			Debug.Assert( array != null );
+
+			int length = array.Length;
+			for( int i = 0; i < length; i ++ ) {
+				array[i] *= scale;
+			}
+		}
+		/// <summary>
+		/// Multiply each element in the array by a specific value 
+		/// </summary>
+		/// <param name="array"></param>
+		/// <param name="scale"></param>
+		/// <param name="start"></param>
+		/// <param name="length"></param>
+		static public void Scale( ComplexF[] array, ComplexF scale, int start, int length ) {
+			Debug.Assert( array != null );
+			Debug.Assert( start >= 0 );
+			Debug.Assert( length >= 0 );
+			Debug.Assert( ( start + length ) < array.Length );
+
+			for( int i = 0; i < length; i ++ ) {
+				array[i + start] *= scale;
+			}
+		}
+
+		//---------------------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Multiply each element in target array with corresponding element in rhs array
+		/// </summary>
+		/// <param name="target"></param>
+		/// <param name="rhs"></param>
+		static public void Multiply( Complex[] target, Complex[] rhs ) {
+			ComplexArray.Multiply( target, rhs, target );
+		}
+		/// <summary>
+		/// Multiply each element in lhs array with corresponding element in rhs array and
+		/// put product in result array
+		/// </summary>
+		/// <param name="lhs"></param>
+		/// <param name="rhs"></param>
+		/// <param name="result"></param>
+		static public void Multiply( Complex[] lhs, Complex[] rhs, Complex[] result ) {
+			Debug.Assert( lhs != null );
+			Debug.Assert( rhs != null );
+			Debug.Assert( result != null );
+			Debug.Assert( lhs.Length == rhs.Length );
+			Debug.Assert( lhs.Length == result.Length );
+
+			int length = lhs.Length;
+			for( int i = 0; i < length; i ++ ) {
+				result[i] = lhs[i] * rhs[i];
+			}
+		}
+
+		/// <summary>
+		/// Multiply each element in target array with corresponding element in rhs array
+		/// </summary>
+		/// <param name="target"></param>
+		/// <param name="rhs"></param>
+		static public void Multiply( ComplexF[] target, ComplexF[] rhs ) {
+			ComplexArray.Multiply( target, rhs, target );
+		}
+		/// <summary>
+		/// Multiply each element in lhs array with corresponding element in rhs array and
+		/// put product in result array
+		/// </summary>
+		/// <param name="lhs"></param>
+		/// <param name="rhs"></param>
+		/// <param name="result"></param>
+		static public void Multiply( ComplexF[] lhs, ComplexF[] rhs, ComplexF[] result ) {
+			Debug.Assert( lhs != null );
+			Debug.Assert( rhs != null );
+			Debug.Assert( result != null );
+			Debug.Assert( lhs.Length == rhs.Length );
+			Debug.Assert( lhs.Length == result.Length );
+
+			int length = lhs.Length;
+			for( int i = 0; i < length; i ++ ) {
+				result[i] = lhs[i] * rhs[i];
+			}
+		}
+
+		//---------------------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Divide each element in target array with corresponding element in rhs array
+		/// </summary>
+		/// <param name="target"></param>
+		/// <param name="rhs"></param>
+		static public void Divide( Complex[] target, Complex[] rhs ) {
+			ComplexArray.Divide( target, rhs, target );
+		}
+		/// <summary>
+		/// Divide each element in lhs array with corresponding element in rhs array and
+		/// put product in result array
+		/// </summary>
+		/// <param name="lhs"></param>
+		/// <param name="rhs"></param>
+		/// <param name="result"></param>
+		static public void Divide( Complex[] lhs, Complex[] rhs, Complex[] result ) {
+			Debug.Assert( lhs != null );
+			Debug.Assert( rhs != null );
+			Debug.Assert( result != null );
+			Debug.Assert( lhs.Length == rhs.Length );
+			Debug.Assert( lhs.Length == result.Length );
+
+			int length = lhs.Length;
+			for( int i = 0; i < length; i ++ ) {
+				result[i] = lhs[i] / rhs[i];
+			}
+		}
+
+		/// <summary>
+		/// Divide each element in target array with corresponding element in rhs array
+		/// </summary>
+		/// <param name="target"></param>
+		/// <param name="rhs"></param>
+		static public void Divide( ComplexF[] target, ComplexF[] rhs ) {
+			ComplexArray.Divide( target, rhs, target );
+		}
+		/// <summary>
+		/// Divide each element in lhs array with corresponding element in rhs array and
+		/// put product in result array
+		/// </summary>
+		/// <param name="lhs"></param>
+		/// <param name="rhs"></param>
+		/// <param name="result"></param>
+		static public void Divide( ComplexF[] lhs, ComplexF[] rhs, ComplexF[] result ) {
+			Debug.Assert( lhs != null );
+			Debug.Assert( rhs != null );
+			Debug.Assert( result != null );
+			Debug.Assert( lhs.Length == rhs.Length );
+			Debug.Assert( lhs.Length == result.Length );
+
+			ComplexF zero = ComplexF.Zero;
+			int length = lhs.Length;
+			for( int i = 0; i < length; i ++ ) {
+				if( rhs[i] != zero ) {
+					result[i] = lhs[i] / rhs[i];
+				}
+				else {
+					result[i] = zero;
+				}
+			}
+		}
+
+		//---------------------------------------------------------------------------------------------
+
+		/*static public void Flip( ComplexF[] array, Size3 size ) {
+			Debug.Assert( array != null );
+
+			ComplexF[]	workspace	= null;
+			ComplexArray.LockWorkspaceF( size.GetTotalLength(), ref workspace );
+			
+			for( int z = 0; z < size.Depth; z ++ ) {
+				for( int y = 0; y < size.Height; y ++ ) {
+					int xyzOffset = 0 + y * size.Width + z * size.Width * size.Height;
+					int abcOffset = size.Width - 1 + ( size.Height - y - 1 ) * size.Width + ( size.Depth - z - 1 ) * size.Width * size.Height;
+					for( int x = 0; x < size.Width; x ++ ) {
+						workspace[ xyzOffset ++ ] = array[ abcOffset -- ];
+					}
+				}
+			}
+
+			for( int i = 0; i < size.GetTotalLength(); i ++ ) {
+				array[ i ] = workspace[ i ];
+			}
+
+			ComplexArray.UnlockWorkspaceF( ref workspace );
+		}  */
+		
+
+		/// <summary>
+		/// Copy an array
+		/// </summary>
+		/// <param name="dest"></param>
+		/// <param name="source"></param>
+		static public void Copy( Complex[] dest, Complex[] source ) {
+			Debug.Assert( dest != null );
+			Debug.Assert( source != null );
+			Debug.Assert( dest.Length == source.Length );
+			for( int i = 0; i < dest.Length; i ++ ) {
+				dest[i] = source[i];
+			}
+		}
+
+		/// <summary>
+		/// Copy an array
+		/// </summary>
+		/// <param name="dest"></param>
+		/// <param name="source"></param>
+		static public void Copy( ComplexF[] dest, ComplexF[] source ) {
+			Debug.Assert( dest != null );
+			Debug.Assert( source != null );
+			Debug.Assert( dest.Length == source.Length );
+			for( int i = 0; i < dest.Length; i ++ ) {
+				dest[i] = source[i];
+			}
+		}
+
+		/// <summary>
+		/// Reverse the elements in the array
+		/// </summary>
+		/// <param name="array"></param>
+		static public void Reverse( Complex[] array ) {
+			Complex temp;
+			int length = array.Length;
+			for( int i = 0; i < length/2; i ++ ) {
+				temp = array[i];
+				array[i] = array[length-1-i];
+				array[length-1-i] = temp;
+			}
+		}
+
+		/// <summary>
+		/// Scale and offset the elements in the array so that the
+		/// overall range is [0, 1]
+		/// </summary>
+		/// <param name="array"></param>
+		static public void Normalize( Complex[] array ) {
+			double min = 0, max = 0;
+			GetLengthRange( array, ref min, ref max );
+			Scale( array, ( 1 / ( max - min ) ) );
+			Offset( array, ( - min / ( max - min ) ) );
+		}
+
+		/// <summary>
+		/// Scale and offset the elements in the array so that the
+		/// overall range is [0, 1]
+		/// </summary>
+		/// <param name="array"></param>
+		static public void Normalize( ComplexF[] array ) {
+			float min = 0, max = 0;
+			GetLengthRange( array, ref min, ref max );
+			Scale( array, ( 1 / ( max - min ) ) );
+			Offset( array, ( - min / ( max - min ) ) );
+		}
+
+		/// <summary>
+		/// Invert each element in the array
+		/// </summary>
+		/// <param name="array"></param>
+		static public void Invert( Complex[] array ) {
+			for( int i = 0; i < array.Length; i ++ ) {
+				array[i] = ((Complex) 1 ) / array[i];
+			}
+		}
+
+		/// <summary>
+		/// Invert each element in the array
+		/// </summary>
+		/// <param name="array"></param>
+		static public void Invert( ComplexF[] array ) {
+			for( int i = 0; i < array.Length; i ++ ) {
+				array[i] = ((ComplexF) 1 ) / array[i];
+			}
+		}
+
+		//----------------------------------------------------------------------------------------
+
+	}
+}

+ 520 - 0
mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/ComplexF.cs

@@ -0,0 +1,520 @@
+/*
+ * BSD Licence:
+ * Copyright (c) 2001, 2002 Ben Houston [ [email protected] ]
+ * Exocortex Technologies [ www.exocortex.org ]
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ * notice, this list of conditions and the following disclaimer in the 
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+
+namespace Exocortex.DSP {
+
+	// Comments? Questions? Bugs? Tell Ben Houston at [email protected]
+	// Version: May 4, 2002
+
+	/// <summary>
+	/// <p>A single-precision complex number representation.</p>
+	/// </summary>
+	[StructLayout(LayoutKind.Sequential)]
+	public struct ComplexF : IComparable, ICloneable {
+
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// The real component of the complex number
+		/// </summary>
+		public float Re;
+
+		/// <summary>
+		/// The imaginary component of the complex number
+		/// </summary>
+		public float Im;
+
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Create a complex number from a real and an imaginary component
+		/// </summary>
+		/// <param name="real"></param>
+		/// <param name="imaginary"></param>
+		public ComplexF( float real, float imaginary ) {
+			this.Re		= (float) real;
+			this.Im	= (float) imaginary;
+		}
+
+		/// <summary>
+		/// Create a complex number based on an existing complex number
+		/// </summary>
+		/// <param name="c"></param>
+		public ComplexF( ComplexF c ) {
+			this.Re		= c.Re;
+			this.Im	= c.Im;
+		}
+
+		/// <summary>
+		/// Create a complex number from a real and an imaginary component
+		/// </summary>
+		/// <param name="real"></param>
+		/// <param name="imaginary"></param>
+		/// <returns></returns>
+		static public ComplexF	FromRealImaginary( float real, float imaginary ) {
+			ComplexF c;
+			c.Re		= (float) real;
+			c.Im = (float) imaginary;
+			return c;
+		}
+
+		/// <summary>
+		/// Create a complex number from a modulus (length) and an argument (radian)
+		/// </summary>
+		/// <param name="modulus"></param>
+		/// <param name="argument"></param>
+		/// <returns></returns>
+		static public ComplexF	FromModulusArgument( float modulus, float argument ) {
+			ComplexF c;
+			c.Re		= (float)( modulus * System.Math.Cos( argument ) );
+			c.Im	= (float)( modulus * System.Math.Sin( argument ) );
+			return c;
+		}
+		
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		object	ICloneable.Clone() {
+			return	new ComplexF( this );
+		}
+		/// <summary>
+		/// Clone the complex number
+		/// </summary>
+		/// <returns></returns>
+		public ComplexF	Clone() {
+			return	new ComplexF( this );
+		}
+		
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// The modulus (length) of the complex number
+		/// </summary>
+		/// <returns></returns>
+		public float	GetModulus() {
+			float	x	= this.Re;
+			float	y	= this.Im;
+			return	(float) Math.Sqrt( x*x + y*y );
+		}
+
+		/// <summary>
+		/// The squared modulus (length^2) of the complex number
+		/// </summary>
+		/// <returns></returns>
+		public float	GetModulusSquared() {
+			float	x	= this.Re;
+			float	y	= this.Im;
+			return	(float) x*x + y*y;
+		}
+
+		/// <summary>
+		/// The argument (radians) of the complex number
+		/// </summary>
+		/// <returns></returns>
+		public float	GetArgument() {
+			return (float) Math.Atan2( this.Im, this.Re );
+		}
+
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Get the conjugate of the complex number
+		/// </summary>
+		/// <returns></returns>
+		public ComplexF GetConjugate() {
+			return FromRealImaginary( this.Re, -this.Im );
+		}
+
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Scale the complex number to 1.
+		/// </summary>
+		public void Normalize() {
+			double	modulus = this.GetModulus();
+			if( modulus == 0 ) {
+				throw new DivideByZeroException( "Can not normalize a complex number that is zero." );
+			}
+			this.Re	= (float)( this.Re / modulus );
+			this.Im	= (float)( this.Im / modulus );
+		}
+
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Convert to a from double precision complex number to a single precison complex number
+		/// </summary>
+		/// <param name="c"></param>
+		/// <returns></returns>
+		public static explicit operator ComplexF ( Complex c ) {
+			ComplexF cF;
+			cF.Re	= (float) c.Re;
+			cF.Im	= (float) c.Im;
+			return cF;
+		}
+		
+		/// <summary>
+		/// Convert from a single precision real number to a complex number
+		/// </summary>
+		/// <param name="f"></param>
+		/// <returns></returns>
+		public static explicit operator ComplexF ( float f ) {
+			ComplexF c;
+			c.Re		= (float) f;
+			c.Im	= (float) 0;
+			return c;
+		}
+
+		/// <summary>
+		/// Convert from a single precision complex to a real number
+		/// </summary>
+		/// <param name="c"></param>
+		/// <returns></returns>
+		public static explicit operator float ( ComplexF c ) {
+			return (float) c.Re;
+		}
+		
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Are these two complex numbers equivalent?
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		/// <returns></returns>
+		public static bool	operator==( ComplexF a, ComplexF b ) {
+			return	( a.Re == b.Re ) && ( a.Im == b.Im );
+		}
+
+		/// <summary>
+		/// Are these two complex numbers different?
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		/// <returns></returns>
+		public static bool	operator!=( ComplexF a, ComplexF b ) {
+			return	( a.Re != b.Re ) || ( a.Im != b.Im );
+		}
+
+		/// <summary>
+		/// Get the hash code of the complex number
+		/// </summary>
+		/// <returns></returns>
+		public override int		GetHashCode() {
+			return	( this.Re.GetHashCode() ^ this.Im.GetHashCode() );
+		}
+
+		/// <summary>
+		/// Is this complex number equivalent to another object?
+		/// </summary>
+		/// <param name="o"></param>
+		/// <returns></returns>
+		public override bool	Equals( object o ) {
+			if( o is ComplexF ) {
+				ComplexF c = (ComplexF) o;
+				return   ( this == c );
+			}
+			return	false;
+		}
+
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Compare to other complex numbers or real numbers
+		/// </summary>
+		/// <param name="o"></param>
+		/// <returns></returns>
+		public int	CompareTo( object o ) {
+			if( o == null ) {
+				return 1;  // null sorts before current
+			}
+			if( o is ComplexF ) {
+				return	this.GetModulus().CompareTo( ((ComplexF)o).GetModulus() );
+			}
+			if( o is float ) {
+				return	this.GetModulus().CompareTo( (float)o );
+			}
+			if( o is Complex ) {
+				return	this.GetModulus().CompareTo( ((Complex)o).GetModulus() );
+			}
+			if( o is double ) {
+				return	this.GetModulus().CompareTo( (double)o );
+			}
+			throw new ArgumentException();
+		}
+
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// This operator doesn't do much. :-)
+		/// </summary>
+		/// <param name="a"></param>
+		/// <returns></returns>
+		public static ComplexF operator+( ComplexF a ) {
+			return a;
+		}
+
+		/// <summary>
+		/// Negate the complex number
+		/// </summary>
+		/// <param name="a"></param>
+		/// <returns></returns>
+		public static ComplexF operator-( ComplexF a ) {
+			a.Re	= -a.Re;
+			a.Im	= -a.Im;
+			return a;
+		}
+
+		/// <summary>
+		/// Add a complex number to a real
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="f"></param>
+		/// <returns></returns>
+		public static ComplexF operator+( ComplexF a, float f ) {
+			a.Re	= (float)( a.Re + f );
+			return a;
+		}
+
+		/// <summary>
+		/// Add a real to a complex number
+		/// </summary>
+		/// <param name="f"></param>
+		/// <param name="a"></param>
+		/// <returns></returns>
+		public static ComplexF operator+( float f, ComplexF a ) {
+			a.Re	= (float)( a.Re + f );
+			return a;
+		}
+
+		/// <summary>
+		/// Add to complex numbers
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		/// <returns></returns>
+		public static ComplexF operator+( ComplexF a, ComplexF b ) {
+			a.Re	= a.Re + b.Re;
+			a.Im	= a.Im + b.Im;
+			return a;
+		}
+
+		/// <summary>
+		/// Subtract a real from a complex number
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="f"></param>
+		/// <returns></returns>
+		public static ComplexF operator-( ComplexF a, float f ) {
+			a.Re	= (float)( a.Re - f );
+			return a;
+		}
+
+		/// <summary>
+		/// Subtract a complex number from a real
+		/// </summary>
+		/// <param name="f"></param>
+		/// <param name="a"></param>
+		/// <returns></returns>
+		public static ComplexF operator-( float f, ComplexF a ) {
+			a.Re	= (float)( f - a.Re );
+			a.Im	= (float)( 0 - a.Im );
+			return a;
+		}
+
+		/// <summary>
+		/// Subtract two complex numbers
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		/// <returns></returns>
+		public static ComplexF operator-( ComplexF a, ComplexF b ) {
+			a.Re	= a.Re - b.Re;
+			a.Im	= a.Im - b.Im;
+			return a;
+		}
+
+		/// <summary>
+		/// Multiply a complex number by a real
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="f"></param>
+		/// <returns></returns>
+		public static ComplexF operator*( ComplexF a, float f ) {
+			a.Re	= (float)( a.Re * f );
+			a.Im	= (float)( a.Im * f );
+			return a;
+		}
+		
+		/// <summary>
+		/// Multiply a real by a complex number
+		/// </summary>
+		/// <param name="f"></param>
+		/// <param name="a"></param>
+		/// <returns></returns>
+		public static ComplexF operator*( float f, ComplexF a ) {
+			a.Re	= (float)( a.Re * f );
+			a.Im	= (float)( a.Im * f );
+			return a;
+		}
+		
+		/// <summary>
+		/// Multiply two complex numbers together
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		/// <returns></returns>
+		public static ComplexF operator*( ComplexF a, ComplexF b ) {
+			// (x + yi)(u + vi) = (xu – yv) + (xv + yu)i. 
+			double	x = a.Re, y = a.Im;
+			double	u = b.Re, v = b.Im;
+			a.Re	= (float)( x*u - y*v );
+			a.Im	= (float)( x*v + y*u );
+			return a;
+		}
+
+		/// <summary>
+		/// Divide a complex number by a real number
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="f"></param>
+		/// <returns></returns>
+		public static ComplexF operator/( ComplexF a, float f ) {
+			if( f == 0 ) {
+				throw new DivideByZeroException();
+			}
+			a.Re	= (float)( a.Re / f );
+			a.Im	= (float)( a.Im / f );
+			return a;
+		}
+		
+		/// <summary>
+		/// Divide a complex number by a complex number
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		/// <returns></returns>
+		public static ComplexF operator/( ComplexF a, ComplexF b ) {
+			double	x = a.Re,	y = a.Im;
+			double	u = b.Re,	v = b.Im;
+			double	denom = u*u + v*v;
+
+			if( denom == 0 ) {
+				throw new DivideByZeroException();
+			}
+			a.Re	= (float)( ( x*u + y*v ) / denom );
+			a.Im	= (float)( ( y*u - x*v ) / denom );
+			return a;
+		}
+
+		/// <summary>
+		/// Parse a complex representation in this fashion: "( %f, %f )"
+		/// </summary>
+		/// <param name="s"></param>
+		/// <returns></returns>
+		static public ComplexF Parse( string s ) {
+			throw new NotImplementedException( "ComplexF ComplexF.Parse( string s ) is not implemented." );
+		}
+		
+		/// <summary>
+		/// Get the string representation
+		/// </summary>
+		/// <returns></returns>
+		public override string ToString() {
+			return	String.Format( "( {0}, {1}i )", this.Re, this.Im );
+		}
+
+		//-----------------------------------------------------------------------------------
+		//-----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Determine whether two complex numbers are almost (i.e. within the tolerance) equivalent.
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		/// <param name="tolerance"></param>
+		/// <returns></returns>
+		static public bool IsEqual( ComplexF a, ComplexF b, float tolerance ) {
+			return
+				( Math.Abs( a.Re - b.Re ) < tolerance ) &&
+				( Math.Abs( a.Im - b.Im ) < tolerance );
+
+		}
+		
+		//----------------------------------------------------------------------------------
+		//----------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Represents zero
+		/// </summary>
+		static public ComplexF	Zero {
+			get	{	return	new ComplexF( 0, 0 );	}
+		}
+
+		/// <summary>
+		/// Represents the result of sqrt( -1 )
+		/// </summary>
+		static public ComplexF	I {
+			get {	return	new ComplexF( 0, 1 );	}
+		}
+
+		/// <summary>
+		/// Represents the largest possible value of ComplexF.
+		/// </summary>
+		static public ComplexF	MaxValue {
+			get {	return	new ComplexF( float.MaxValue, float.MaxValue );	}
+		}
+
+		/// <summary>
+		/// Represents the smallest possible value of ComplexF.
+		/// </summary>
+		static public ComplexF	MinValue {
+			get {	return	new ComplexF( float.MinValue, float.MinValue );	}
+		}
+
+
+		//----------------------------------------------------------------------------------
+		//----------------------------------------------------------------------------------
+	}
+
+}

+ 158 - 0
mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/ComplexMath.cs

@@ -0,0 +1,158 @@
+/*
+ * BSD Licence:
+ * Copyright (c) 2001, 2002 Ben Houston [ [email protected] ]
+ * Exocortex Technologies [ www.exocortex.org ]
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ * notice, this list of conditions and the following disclaimer in the 
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+using System;
+using System.Diagnostics;
+
+
+namespace Exocortex.DSP {
+
+	// Comments? Questions? Bugs? Tell Ben Houston at [email protected]
+	// Version: May 4, 2002
+
+	/// <summary>
+	/// <p>Various mathematical functions for complex numbers.</p>
+	/// </summary>
+	public class ComplexMath {
+		
+		//---------------------------------------------------------------------------------------------------
+
+		private ComplexMath() {
+		}
+
+		//---------------------------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Swap two complex numbers
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		static public void Swap( ref Complex a, ref Complex b ) {
+			Complex temp = a;
+			a = b;
+			b = temp;
+		}
+
+		/// <summary>
+		/// Swap two complex numbers
+		/// </summary>
+		/// <param name="a"></param>
+		/// <param name="b"></param>
+		static public void Swap( ref ComplexF a, ref ComplexF b ) {
+			ComplexF temp = a;
+			a = b;
+			b = temp;
+		}
+		
+		//---------------------------------------------------------------------------------------------------
+
+		static private double	_halfOfRoot2	= 0.5 * Math.Sqrt( 2 );
+
+		/// <summary>
+		/// Calculate the square root of a complex number
+		/// </summary>
+		/// <param name="c"></param>
+		/// <returns></returns>
+		static public ComplexF	Sqrt( ComplexF c ) {
+			double	x	= c.Re;
+			double	y	= c.Im;
+
+			double	modulus	= Math.Sqrt( x*x + y*y );
+			int		sign	= ( y < 0 ) ? -1 : 1;
+
+			c.Re		= (float)( _halfOfRoot2 * Math.Sqrt( modulus + x ) );
+			c.Im	= (float)( _halfOfRoot2 * sign * Math.Sqrt( modulus - x ) );
+
+			return	c;
+		}
+
+		/// <summary>
+		/// Calculate the square root of a complex number
+		/// </summary>
+		/// <param name="c"></param>
+		/// <returns></returns>
+		static public Complex	Sqrt( Complex c ) {
+			double	x	= c.Re;
+			double	y	= c.Im;
+
+			double	modulus	= Math.Sqrt( x*x + y*y );
+			int		sign	= ( y < 0 ) ? -1 : 1;
+
+			c.Re		= (double)( _halfOfRoot2 * Math.Sqrt( modulus + x ) );
+			c.Im	= (double)( _halfOfRoot2 * sign * Math.Sqrt( modulus - x ) );
+
+			return	c;
+		}
+
+		//---------------------------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Calculate the power of a complex number
+		/// </summary>
+		/// <param name="c"></param>
+		/// <param name="exponent"></param>
+		/// <returns></returns>
+		static public ComplexF	Pow( ComplexF c, double exponent ) {
+			double	x	= c.Re;
+			double	y	= c.Im;
+			
+			double	modulus		= Math.Pow( x*x + y*y, exponent * 0.5 );
+			double	argument	= Math.Atan2( y, x ) * exponent;
+
+			c.Re		= (float)( modulus * System.Math.Cos( argument ) );
+			c.Im = (float)( modulus * System.Math.Sin( argument ) );
+
+			return	c;
+		}
+
+		/// <summary>
+		/// Calculate the power of a complex number
+		/// </summary>
+		/// <param name="c"></param>
+		/// <param name="exponent"></param>
+		/// <returns></returns>
+		static public Complex	Pow( Complex c, double exponent ) {
+			double	x	= c.Re;
+			double	y	= c.Im;
+			
+			double	modulus		= Math.Pow( x*x + y*y, exponent * 0.5 );
+			double	argument	= Math.Atan2( y, x ) * exponent;
+
+			c.Re		= (double)( modulus * System.Math.Cos( argument ) );
+			c.Im = (double)( modulus * System.Math.Sin( argument ) );
+
+			return	c;
+		}
+		
+		//---------------------------------------------------------------------------------------------------
+
+	}
+}

+ 306 - 0
mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/ComplexStats.cs

@@ -0,0 +1,306 @@
+/*
+ * BSD Licence:
+ * Copyright (c) 2001, 2002 Ben Houston [ [email protected] ]
+ * Exocortex Technologies [ www.exocortex.org ]
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ * notice, this list of conditions and the following disclaimer in the 
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+using System;
+using System.Diagnostics;
+
+namespace Exocortex.DSP
+{
+	// Comments? Questions? Bugs? Tell Ben Houston at [email protected]
+	// Version: May 4, 2002
+	
+	/// <summary>
+	/// <p>A set of statistical utilities for complex number arrays</p>
+	/// </summary>
+	public class ComplexStats
+	{
+		//---------------------------------------------------------------------------------------------
+
+		private ComplexStats() {
+		}
+
+		//---------------------------------------------------------------------------------------------
+		//--------------------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Calculate the sum
+		/// </summary>
+		/// <param name="data"></param>
+		/// <returns></returns>
+		static public  ComplexF		Sum( ComplexF[] data ) {
+			Debug.Assert( data != null );
+			return	SumRecursion( data, 0, data.Length );
+		}
+		static private ComplexF		SumRecursion( ComplexF[] data, int start, int end ) {
+			Debug.Assert( 0 <= start, "start = " + start );
+			Debug.Assert( start < end, "start = " + start + " and end = " + end );
+			Debug.Assert( end <= data.Length, "end = " + end + " and data.Length = " + data.Length );
+			if( ( end - start ) <= 1000 ) {
+				ComplexF sum = ComplexF.Zero;
+				for( int i = start; i < end; i ++ ) {
+					sum += data[ i ];
+				
+				}
+				return	sum;
+			}
+			else {
+				int middle = ( start + end ) >> 1;
+				return	SumRecursion( data, start, middle ) + SumRecursion( data, middle, end );
+			}
+		}
+
+		/// <summary>
+		/// Calculate the sum
+		/// </summary>
+		/// <param name="data"></param>
+		/// <returns></returns>
+		static public  Complex		Sum( Complex[] data ) {
+			Debug.Assert( data != null );
+			return	SumRecursion( data, 0, data.Length );
+		}
+		static private Complex		SumRecursion( Complex[] data, int start, int end ) {
+			Debug.Assert( 0 <= start, "start = " + start );
+			Debug.Assert( start < end, "start = " + start + " and end = " + end );
+			Debug.Assert( end <= data.Length, "end = " + end + " and data.Length = " + data.Length );
+			if( ( end - start ) <= 1000 ) {
+				Complex sum = Complex.Zero;
+				for( int i = start; i < end; i ++ ) {
+					sum += data[ i ];
+				
+				}
+				return	sum;
+			}
+			else {
+				int middle = ( start + end ) >> 1;
+				return	SumRecursion( data, start, middle ) + SumRecursion( data, middle, end );
+			}
+		}
+
+		//--------------------------------------------------------------------------------------------
+		//--------------------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Calculate the sum of squares
+		/// </summary>
+		/// <param name="data"></param>
+		/// <returns></returns>
+		static public ComplexF		SumOfSquares( ComplexF[] data ) {
+			Debug.Assert( data != null );
+			return	SumOfSquaresRecursion( data, 0, data.Length );
+		}
+		static private ComplexF		SumOfSquaresRecursion( ComplexF[] data, int start, int end ) {
+			Debug.Assert( 0 <= start, "start = " + start );
+			Debug.Assert( start < end, "start = " + start + " and end = " + end );
+			Debug.Assert( end <= data.Length, "end = " + end + " and data.Length = " + data.Length );
+			if( ( end - start ) <= 1000 ) {
+				ComplexF sumOfSquares = ComplexF.Zero;
+				for( int i = start; i < end; i ++ ) {
+					sumOfSquares += data[ i ] * data[ i ];
+				
+				}
+				return	sumOfSquares;
+			}
+			else {
+				int middle = ( start + end ) >> 1;
+				return	SumOfSquaresRecursion( data, start, middle ) + SumOfSquaresRecursion( data, middle, end );
+			}
+		}
+
+		/// <summary>
+		/// Calculate the sum of squares
+		/// </summary>
+		/// <param name="data"></param>
+		/// <returns></returns>
+		static public Complex		SumOfSquares( Complex[] data ) {
+			Debug.Assert( data != null );
+			return	SumOfSquaresRecursion( data, 0, data.Length );
+		}
+		static private Complex		SumOfSquaresRecursion( Complex[] data, int start, int end ) {
+			Debug.Assert( 0 <= start, "start = " + start );
+			Debug.Assert( start < end, "start = " + start + " and end = " + end );
+			Debug.Assert( end <= data.Length, "end = " + end + " and data.Length = " + data.Length );
+			if( ( end - start ) <= 1000 ) {
+				Complex sumOfSquares = Complex.Zero;
+				for( int i = start; i < end; i ++ ) {
+					sumOfSquares += data[ i ] * data[ i ];
+				
+				}
+				return	sumOfSquares;
+			}
+			else {
+				int middle = ( start + end ) >> 1;
+				return	SumOfSquaresRecursion( data, start, middle ) + SumOfSquaresRecursion( data, middle, end );
+			}
+		}
+
+		//--------------------------------------------------------------------------------------------
+		//--------------------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Calculate the mean (average)
+		/// </summary>
+		/// <param name="data"></param>
+		/// <returns></returns>
+		static public ComplexF		Mean( ComplexF[] data ) {
+			return	ComplexStats.Sum( data ) / data.Length;
+		}
+
+		/// <summary>
+		/// Calculate the mean (average)
+		/// </summary>
+		/// <param name="data"></param>
+		/// <returns></returns>
+		static public Complex		Mean( Complex[] data ) {
+			return	ComplexStats.Sum( data ) / data.Length;
+		}
+
+		/// <summary>
+		/// Calculate the variance
+		/// </summary>
+		/// <param name="data"></param>
+		/// <returns></returns>
+		static public ComplexF	Variance( ComplexF[] data ) {
+			Debug.Assert( data != null );
+			if( data.Length == 0 ) {
+				throw new DivideByZeroException( "length of data is zero" );
+			}
+			return	ComplexStats.SumOfSquares( data ) / data.Length - ComplexStats.Sum( data );
+		}
+		/// <summary>
+		/// Calculate the variance 
+		/// </summary>
+		/// <param name="data"></param>
+		/// <returns></returns>
+		static public Complex	Variance( Complex[] data ) {
+			Debug.Assert( data != null );
+			if( data.Length == 0 ) {
+				throw new DivideByZeroException( "length of data is zero" );
+			}
+			return	ComplexStats.SumOfSquares( data ) / data.Length - ComplexStats.Sum( data );
+		}
+
+		/// <summary>
+		/// Calculate the standard deviation
+		/// </summary>
+		/// <param name="data"></param>
+		/// <returns></returns>
+		static public ComplexF	StdDev( ComplexF[] data ) {
+			Debug.Assert( data != null );
+			if( data.Length == 0 ) {
+				throw new DivideByZeroException( "length of data is zero" );
+			}
+			return	ComplexMath.Sqrt( ComplexStats.Variance( data ) );
+		}
+		/// <summary>
+		/// Calculate the standard deviation 
+		/// </summary>
+		/// <param name="data"></param>
+		/// <returns></returns>
+		static public Complex	StdDev( Complex[] data ) {
+			Debug.Assert( data != null );
+			if( data.Length == 0 ) {
+				throw new DivideByZeroException( "length of data is zero" );
+			}
+			return	ComplexMath.Sqrt( ComplexStats.Variance( data ) );
+		}
+
+		//--------------------------------------------------------------------------------------------
+		//--------------------------------------------------------------------------------------------
+
+		/// <summary>
+		/// Calculate the root mean squared (RMS) error between two sets of data.
+		/// </summary>
+		/// <param name="alpha"></param>
+		/// <param name="beta"></param>
+		/// <returns></returns>
+		static public float	RMSError( ComplexF[] alpha, ComplexF[] beta ) {
+			Debug.Assert( alpha != null );
+			Debug.Assert( beta != null );
+			Debug.Assert( beta.Length == alpha.Length );
+
+			return (float) Math.Sqrt( SumOfSquaredErrorRecursion( alpha, beta, 0, alpha.Length ) );
+		}
+		static private float	SumOfSquaredErrorRecursion( ComplexF[] alpha, ComplexF[] beta, int start, int end ) {
+			Debug.Assert( 0 <= start, "start = " + start );
+			Debug.Assert( start < end, "start = " + start + " and end = " + end );
+			Debug.Assert( end <= alpha.Length, "end = " + end + " and alpha.Length = " + alpha.Length );
+			Debug.Assert( beta.Length == alpha.Length );
+			if( ( end - start ) <= 1000 ) {
+				float sumOfSquaredError = 0;
+				for( int i = start; i < end; i ++ ) {
+					ComplexF delta = beta[ i ] - alpha[ i ];
+					sumOfSquaredError += ( delta.Re * delta.Re ) + ( delta.Im * delta.Im );
+				
+				}
+				return	sumOfSquaredError;
+			}
+			else {
+				int middle = ( start + end ) >> 1;
+				return	SumOfSquaredErrorRecursion( alpha, beta, start, middle ) + SumOfSquaredErrorRecursion( alpha, beta, middle, end );
+			}
+		}
+
+		/// <summary>
+		/// Calculate the root mean squared (RMS) error between two sets of data.
+		/// </summary>
+		/// <param name="alpha"></param>
+		/// <param name="beta"></param>
+		/// <returns></returns>
+		static public double	RMSError( Complex[] alpha, Complex[] beta ) {
+			Debug.Assert( alpha != null );
+			Debug.Assert( beta != null );
+			Debug.Assert( beta.Length == alpha.Length );
+
+			return Math.Sqrt( SumOfSquaredErrorRecursion( alpha, beta, 0, alpha.Length ) );
+		}
+		static private double	SumOfSquaredErrorRecursion( Complex[] alpha, Complex[] beta, int start, int end ) {
+			Debug.Assert( 0 <= start, "start = " + start );
+			Debug.Assert( start < end, "start = " + start + " and end = " + end );
+			Debug.Assert( end <= alpha.Length, "end = " + end + " and alpha.Length = " + alpha.Length );
+			Debug.Assert( beta.Length == alpha.Length );
+			if( ( end - start ) <= 1000 ) {
+				double sumOfSquaredError = 0;
+				for( int i = start; i < end; i ++ ) {
+					Complex delta = beta[ i ] - alpha[ i ];
+					sumOfSquaredError += ( delta.Re * delta.Re ) + ( delta.Im * delta.Im );
+				
+				}
+				return	sumOfSquaredError;
+			}
+			else {
+				int middle = ( start + end ) >> 1;
+				return	SumOfSquaredErrorRecursion( alpha, beta, start, middle ) + SumOfSquaredErrorRecursion( alpha, beta, middle, end );
+			}
+		}
+
+
+	}
+}

+ 135 - 0
mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/Exocortex.DSP.v1.csproj

@@ -0,0 +1,135 @@
+<VisualStudioProject>
+    <CSHARP
+        ProjectType = "Local"
+        ProductVersion = "7.10.3077"
+        SchemaVersion = "2.0"
+        ProjectGuid = "{1904A41B-D1B8-40E5-ADBB-728DDCF7C816}"
+    >
+        <Build>
+            <Settings
+                ApplicationIcon = ""
+                AssemblyKeyContainerName = ""
+                AssemblyName = "Exocortex.DSP.v1"
+                AssemblyOriginatorKeyFile = ""
+                DefaultClientScript = "JScript"
+                DefaultHTMLPageLayout = "Grid"
+                DefaultTargetSchema = "IE50"
+                DelaySign = "false"
+                OutputType = "Library"
+                PreBuildEvent = ""
+                PostBuildEvent = ""
+                RootNamespace = "Exocortex.DSP"
+                RunPostBuildEvent = "OnBuildSuccess"
+                StartupObject = ""
+            >
+                <Config
+                    Name = "Debug"
+                    AllowUnsafeBlocks = "false"
+                    BaseAddress = "285212672"
+                    CheckForOverflowUnderflow = "true"
+                    ConfigurationOverrideFile = ""
+                    DefineConstants = "DEBUG;TRACE"
+                    DocumentationFile = "doc\Exocortex.DSP.xml"
+                    DebugSymbols = "true"
+                    FileAlignment = "4096"
+                    IncrementalBuild = "true"
+                    NoStdLib = "false"
+                    NoWarn = ""
+                    Optimize = "true"
+                    OutputPath = "bin\Debug\"
+                    RegisterForComInterop = "false"
+                    RemoveIntegerChecks = "false"
+                    TreatWarningsAsErrors = "false"
+                    WarningLevel = "4"
+                />
+                <Config
+                    Name = "Release"
+                    AllowUnsafeBlocks = "false"
+                    BaseAddress = "285212672"
+                    CheckForOverflowUnderflow = "true"
+                    ConfigurationOverrideFile = ""
+                    DefineConstants = "TRACE"
+                    DocumentationFile = "doc\Exocortex.DSP.xml"
+                    DebugSymbols = "false"
+                    FileAlignment = "4096"
+                    IncrementalBuild = "false"
+                    NoStdLib = "false"
+                    NoWarn = ""
+                    Optimize = "true"
+                    OutputPath = "bin\Release\"
+                    RegisterForComInterop = "false"
+                    RemoveIntegerChecks = "false"
+                    TreatWarningsAsErrors = "false"
+                    WarningLevel = "4"
+                />
+            </Settings>
+            <References>
+                <Reference
+                    Name = "System"
+                    AssemblyName = "System"
+                    HintPath = "..\..\..\WINNT\Microsoft.NET\Framework\v1.0.3705\System.dll"
+                />
+                <Reference
+                    Name = "System.Data"
+                    AssemblyName = "System.Data"
+                    HintPath = "..\..\..\WINNT\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
+                />
+                <Reference
+                    Name = "System.XML"
+                    AssemblyName = "System.Xml"
+                    HintPath = "..\..\..\WINNT\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
+                />
+                <Reference
+                    Name = "System.Drawing"
+                    AssemblyName = "System.Drawing"
+                    HintPath = "..\..\..\WINNT\Microsoft.NET\Framework\v1.0.3705\System.Drawing.dll"
+                />
+            </References>
+        </Build>
+        <Files>
+            <Include>
+                <File
+                    RelPath = "AssemblyInfo.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "Complex.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "ComplexArray.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "ComplexF.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "ComplexMath.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "ComplexStats.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "Fourier.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "FourierDirection.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+            </Include>
+        </Files>
+    </CSHARP>
+</VisualStudioProject>
+

+ 1346 - 0
mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/Fourier.cs

@@ -0,0 +1,1346 @@
+/*
+ * BSD Licence:
+ * Copyright (c) 2001, 2002 Ben Houston [ [email protected] ]
+ * Exocortex Technologies [ www.exocortex.org ]
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ * notice, this list of conditions and the following disclaimer in the 
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+
+//using Exocortex.Imaging;
+
+namespace Exocortex.DSP {
+
+	// Comments? Questions? Bugs? Tell Ben Houston at [email protected]
+	// Version: May 4, 2002
+
+	/// <summary>
+	/// <p>Static functions for doing various Fourier Operations.</p>
+	/// </summary>
+	public class Fourier {
+		
+		//======================================================================================
+
+		private Fourier() {
+		}
+
+		//======================================================================================
+
+		static private void Swap( ref float a, ref float b ) {
+			float temp = a;
+			a = b;
+			b = temp;
+		}
+		static private void Swap( ref double a, ref double b ) {
+			double temp = a;
+			a = b;
+			b = temp;
+		}
+		static private void Swap( ref ComplexF a, ref ComplexF b ) {
+			ComplexF temp = a;
+			a = b;
+			b = temp;
+		}
+		static private void Swap( ref Complex a, ref Complex b ) {
+			Complex temp = a;
+			a = b;
+			b = temp;
+		}
+		
+		//-------------------------------------------------------------------------------------
+		
+		private const int	cMaxLength	= 4096;
+		private const int	cMinLength	= 1;
+
+		private const int	cMaxBits	= 12;
+		private const int	cMinBits	= 0;
+	
+
+		static private bool	IsPowerOf2( int x ) {
+			return	(x & (x - 1)) == 0;
+			//return	( x == Pow2( Log2( x ) ) );
+		}
+		static private int	Pow2( int exponent ) {
+			if( exponent >= 0 && exponent < 31 ) {
+				return	1 << exponent;
+			}
+			return	0;
+		}
+		static private int	Log2( int x ) {
+			if( x <= 65536 ) {
+				if( x <= 256 ) {
+					if( x <= 16 ) {
+						if( x <= 4 ) {	
+							if( x <= 2 ) {
+								if( x <= 1 ) {
+									return	0;
+								}
+								return	1;	
+							}
+							return	2;				
+						}
+						if( x <= 8 )
+							return	3;			
+						return	4;				
+					}
+					if( x <= 64 ) {
+						if( x <= 32 )
+							return	5;	
+						return	6;				
+					}
+					if( x <= 128 )
+						return	7;		
+					return	8;				
+				}
+				if( x <= 4096 ) {	
+					if( x <= 1024 ) {	
+						if( x <= 512 )
+							return	9;			
+						return	10;				
+					}
+					if( x <= 2048 )
+						return	11;			
+					return	12;				
+				}
+				if( x <= 16384 ) {
+					if( x <= 8192 )
+						return	13;			
+					return	14;				
+				}
+				if( x <= 32768 )
+					return	15;	
+				return	16;	
+			}
+			if( x <= 16777216 ) {
+				if( x <= 1048576 ) {
+					if( x <= 262144 ) {	
+						if( x <= 131072 )
+							return	17;			
+						return	18;				
+					}
+					if( x <= 524288 )
+						return	19;			
+					return	20;				
+				}
+				if( x <= 4194304 ) {
+					if( x <= 2097152 )
+						return	21;	
+					return	22;				
+				}
+				if( x <= 8388608 )
+					return	23;		
+				return	24;				
+			}
+			if( x <= 268435456 ) {	
+				if( x <= 67108864 ) {	
+					if( x <= 33554432 )
+						return	25;			
+					return	26;				
+				}
+				if( x <= 134217728 )
+					return	27;			
+				return	28;				
+			}
+			if( x <= 1073741824 ) {
+				if( x <= 536870912 )
+					return	29;			
+				return	30;				
+			}
+			//	since int is unsigned it can never be higher than 2,147,483,647
+			//	if( x <= 2147483648 )
+			//		return	31;	
+			//	return	32;	
+			return	31;
+		}
+
+		//-------------------------------------------------------------------------------------
+		//-------------------------------------------------------------------------------------
+
+		static private int	ReverseBits( int index, int numberOfBits ) {
+			Debug.Assert( numberOfBits >= cMinBits );
+			Debug.Assert( numberOfBits <= cMaxBits );
+
+			int reversedIndex = 0;
+			for( int i = 0; i < numberOfBits; i ++ ) {
+				reversedIndex = ( reversedIndex << 1 ) | ( index & 1 );
+				index = ( index >> 1 );
+			}
+			return reversedIndex;
+		}
+
+		//-------------------------------------------------------------------------------------
+		
+		static private int[][]	_reversedBits	= new int[ cMaxBits ][];
+		static private int[]		GetReversedBits( int numberOfBits ) {
+			Debug.Assert( numberOfBits >= cMinBits );
+			Debug.Assert( numberOfBits <= cMaxBits );
+			if( _reversedBits[ numberOfBits - 1 ] == null ) {
+				int		maxBits = Fourier.Pow2( numberOfBits );
+				int[]	reversedBits = new int[ maxBits ];
+				for( int i = 0; i < maxBits; i ++ ) {
+					int oldBits = i;
+					int newBits = 0;
+					for( int j = 0; j < numberOfBits; j ++ ) {
+						newBits = ( newBits << 1 ) | ( oldBits & 1 );
+						oldBits = ( oldBits >> 1 );
+					}
+					reversedBits[ i ] = newBits;
+				}
+				_reversedBits[ numberOfBits - 1 ] = reversedBits;
+			}
+			return	_reversedBits[ numberOfBits - 1 ];
+		}
+
+		//-------------------------------------------------------------------------------------
+
+		static private void ReorderArray( float[] data ) {
+			Debug.Assert( data != null );
+
+			int length = data.Length / 2;
+			
+			Debug.Assert( Fourier.IsPowerOf2( length ) == true );
+			Debug.Assert( length >= cMinLength );
+			Debug.Assert( length <= cMaxLength );
+
+			int[] reversedBits = Fourier.GetReversedBits( Fourier.Log2( length ) );
+			for( int i = 0; i < length; i ++ ) {
+				int swap = reversedBits[ i ];
+				if( swap > i ) {
+					Fourier.Swap( ref data[ (i<<1) ], ref data[ (swap<<1) ] );
+					Fourier.Swap( ref data[ (i<<1) + 1 ], ref data[ (swap<<1) + 1 ] );
+				}
+			}
+		}
+
+		static private void ReorderArray( double[] data ) {
+			Debug.Assert( data != null );
+
+			int length = data.Length / 2;
+			
+			Debug.Assert( Fourier.IsPowerOf2( length ) == true );
+			Debug.Assert( length >= cMinLength );
+			Debug.Assert( length <= cMaxLength );
+
+			int[] reversedBits = Fourier.GetReversedBits( Fourier.Log2( length ) );
+			for( int i = 0; i < length; i ++ ) {
+				int swap = reversedBits[ i ];
+				if( swap > i ) {
+					Fourier.Swap( ref data[ i<<1 ], ref data[ swap<<1 ] );
+					Fourier.Swap( ref data[ i<<1 + 1 ], ref data[ swap<<1 + 1 ] );
+				}
+			}
+		}
+
+		static private void ReorderArray( Complex[] data ) {
+			Debug.Assert( data != null );
+	
+			int length = data.Length;
+			
+			Debug.Assert( Fourier.IsPowerOf2( length ) == true );
+			Debug.Assert( length >= cMinLength );
+			Debug.Assert( length <= cMaxLength );
+			
+			int[] reversedBits = Fourier.GetReversedBits( Fourier.Log2( length ) );
+			for( int i = 0; i < length; i ++ ) {
+				int swap = reversedBits[ i ];
+				if( swap > i ) {
+					Complex temp = data[ i ];
+					data[ i ] = data[ swap ];
+					data[ swap ] = temp;
+				}
+			}
+		}
+
+		static private void ReorderArray( ComplexF[] data ) {
+			Debug.Assert( data != null );
+
+			int length = data.Length;
+			
+			Debug.Assert( Fourier.IsPowerOf2( length ) == true );
+			Debug.Assert( length >= cMinLength );
+			Debug.Assert( length <= cMaxLength );
+
+			int[] reversedBits = Fourier.GetReversedBits( Fourier.Log2( length ) );
+			for( int i = 0; i < length; i ++ ) {
+				int swap = reversedBits[ i ];
+				if( swap > i ) {
+					ComplexF temp = data[ i ];
+					data[ i ] = data[ swap ];
+					data[ swap ] = temp;
+				}
+			}
+		}
+
+		//======================================================================================
+
+		private static int[][]	_reverseBits = null;
+
+		private static int	_ReverseBits( int bits, int n ) {
+			int bitsReversed = 0;
+			for( int i = 0; i < n; i ++ ) {
+				bitsReversed = ( bitsReversed << 1 ) | ( bits & 1 );
+				bits = ( bits >> 1 );
+			}
+			return bitsReversed;
+		}
+
+		private static void	InitializeReverseBits( int levels ) {
+			_reverseBits = new int[levels + 1][];
+			for( int j = 0; j < ( levels + 1 ); j ++ ) {
+				int count = (int) Math.Pow( 2, j );
+				_reverseBits[j] = new int[ count ];
+				for( int i = 0; i < count; i ++ ) {
+					_reverseBits[j][i] = _ReverseBits( i, j );
+				}
+			}
+		}
+
+		private static int _lookupTabletLength = -1;
+		private static double[,][]	_uRLookup	= null;
+		private static double[,][]	_uILookup	= null;
+		private static	float[,][]	_uRLookupF	= null;
+		private static	float[,][]	_uILookupF	= null;
+
+		private static void	SyncLookupTableLength( int length ) {
+			Debug.Assert( length < 1024*10 );
+			Debug.Assert( length >= 0 );
+			if( length > _lookupTabletLength ) {
+				int level = (int) Math.Ceiling( Math.Log( length, 2 ) );
+				Fourier.InitializeReverseBits( level );
+				Fourier.InitializeComplexRotations( level );
+				//_cFFTData	= new Complex[ Math2.CeilingBase( length, 2 ) ];
+				//_cFFTDataF	= new ComplexF[ Math2.CeilingBase( length, 2 ) ];
+				_lookupTabletLength = length;
+			}
+		}
+
+		private static int	GetLookupTableLength() {
+			return	_lookupTabletLength;
+		}
+
+		private static void	ClearLookupTables() {
+			_uRLookup	= null;
+			_uILookup	= null;
+			_uRLookupF	= null;
+			_uILookupF	= null;
+			_lookupTabletLength	= -1;
+		}
+		
+		private static void InitializeComplexRotations( int levels ) {
+			int ln = levels;
+			//_wRLookup = new float[ levels + 1, 2 ];
+			//_wILookup = new float[ levels + 1, 2 ];
+			
+			_uRLookup = new double[ levels + 1, 2 ][];
+			_uILookup = new double[ levels + 1, 2 ][];
+
+			_uRLookupF = new float[ levels + 1, 2 ][];
+			_uILookupF = new float[ levels + 1, 2 ][];
+
+			int N = 1;
+			for( int level = 1; level <= ln; level ++ ) {
+				int M = N;
+				N <<= 1;
+
+				//float scale = (float)( 1 / Math.Sqrt( 1 << ln ) );
+
+				// positive sign ( i.e. [M,0] )
+				{
+					double	uR = 1;
+					double	uI = 0;
+					double	angle = (double) Math.PI / M * 1;
+					double	wR = (double) Math.Cos( angle );
+					double	wI = (double) Math.Sin( angle );
+
+					_uRLookup[level,0] = new double[ M ];
+					_uILookup[level,0] = new double[ M ];
+					_uRLookupF[level,0] = new float[ M ];
+					_uILookupF[level,0] = new float[ M ];
+
+					for( int j = 0; j < M; j ++ ) {
+						_uRLookupF[level,0][j] = (float)( _uRLookup[level,0][j] = uR );
+						_uILookupF[level,0][j] = (float)( _uILookup[level,0][j] = uI );
+						double	uwI = uR*wI + uI*wR;
+						uR = uR*wR - uI*wI;
+						uI = uwI;
+					}
+				}
+				{
+
+
+				// negative sign ( i.e. [M,1] )
+					double	uR = 1;
+                    double	uI = 0;
+					double	angle = (double) Math.PI / M * -1;
+					double	wR = (double) Math.Cos( angle );
+					double	wI = (double) Math.Sin( angle );
+
+					_uRLookup[level,1] = new double[ M ];
+					_uILookup[level,1] = new double[ M ];
+					_uRLookupF[level,1] = new float[ M ];
+					_uILookupF[level,1] = new float[ M ];
+
+					for( int j = 0; j < M; j ++ ) {
+						_uRLookupF[level,1][j] = (float)( _uRLookup[level,1][j] = uR );
+						_uILookupF[level,1][j] = (float)( _uILookup[level,1][j] = uI );
+						double	uwI = uR*wI + uI*wR;
+						uR = uR*wR - uI*wI;
+						uI = uwI;
+					}
+				}
+
+			}
+		}
+		
+		//======================================================================================
+		//======================================================================================
+
+		static private bool		_bufferFLocked	= false;
+		static private float[]	_bufferF		= new float[ 0 ];
+
+		static private void		LockBufferF( int length, ref float[] buffer ) {
+			Debug.Assert( _bufferFLocked == false );
+			_bufferFLocked = true;
+			if( length >= _bufferF.Length ) {
+				_bufferF	= new float[ length ];
+			}
+			buffer =	_bufferF;
+		}
+		static private void		UnlockBufferF( ref float[] buffer ) {
+			Debug.Assert( _bufferF == buffer );
+			Debug.Assert( _bufferFLocked == true );
+			_bufferFLocked = false;
+			buffer = null;
+		}
+
+		private static void	LinearFFT( float[] data, int start, int inc, int length, FourierDirection direction ) {
+			Debug.Assert( data != null );
+			Debug.Assert( start >= 0 );
+			Debug.Assert( inc >= 1 );
+			Debug.Assert( length >= 1 );
+			Debug.Assert( ( start + inc * ( length - 1 ) ) * 2 < data.Length );
+			
+			// copy to buffer
+			float[]	buffer = null;
+			LockBufferF( length * 2, ref buffer );
+			int j = start;
+			for( int i = 0; i < length * 2; i ++ ) {
+				buffer[ i ] = data[ j ];
+				j += inc;
+			}
+
+			FFT( buffer, length, direction );
+
+			// copy from buffer
+			j = start;
+			for( int i = 0; i < length; i ++ ) {
+				data[ j ] = buffer[ i ];
+				j += inc;
+			}
+			UnlockBufferF( ref buffer );
+		}
+
+		private static void	LinearFFT_Quick( float[] data, int start, int inc, int length, FourierDirection direction ) {
+			/*Debug.Assert( data != null );
+			Debug.Assert( start >= 0 );
+			Debug.Assert( inc >= 1 );
+			Debug.Assert( length >= 1 );
+			Debug.Assert( ( start + inc * ( length - 1 ) ) * 2 < data.Length );*/
+			
+			// copy to buffer
+			float[]	buffer = null;
+			LockBufferF( length * 2, ref buffer );
+			int j = start;
+			for( int i = 0; i < length * 2; i ++ ) {
+				buffer[ i ] = data[ j ];
+				j += inc;
+			}
+
+			FFT_Quick( buffer, length, direction );
+
+			// copy from buffer
+			j = start;
+			for( int i = 0; i < length; i ++ ) {
+				data[ j ] = buffer[ i ];
+				j += inc;
+			}
+			UnlockBufferF( ref buffer );
+		}
+
+		//======================================================================================
+		//======================================================================================
+		
+		static private bool			_bufferCFLocked	= false;
+		static private ComplexF[]	_bufferCF		= new ComplexF[ 0 ];
+
+		static private void		LockBufferCF( int length, ref ComplexF[] buffer ) {
+			Debug.Assert( length >= 0 );
+			Debug.Assert( _bufferCFLocked == false );
+			
+			_bufferCFLocked = true;
+			if( length != _bufferCF.Length ) {
+				_bufferCF	= new ComplexF[ length ];
+			}
+			buffer =	_bufferCF;
+		}
+		static private void		UnlockBufferCF( ref ComplexF[] buffer ) {
+			Debug.Assert( _bufferCF == buffer );
+			Debug.Assert( _bufferCFLocked == true );
+			
+			_bufferCFLocked = false;
+			buffer = null;
+		}
+
+		private static void	LinearFFT( ComplexF[] data, int start, int inc, int length, FourierDirection direction ) {
+			Debug.Assert( data != null );
+			Debug.Assert( start >= 0 );
+			Debug.Assert( inc >= 1 );
+			Debug.Assert( length >= 1 );
+			Debug.Assert( ( start + inc * ( length - 1 ) ) < data.Length );
+			
+			// copy to buffer
+			ComplexF[]	buffer = null;
+			LockBufferCF( length, ref buffer );
+			int j = start;
+			for( int i = 0; i < length; i ++ ) {
+				buffer[ i ] = data[ j ];
+				j += inc;
+			}
+
+			FFT( buffer, length, direction );
+
+			// copy from buffer
+			j = start;
+			for( int i = 0; i < length; i ++ ) {
+				data[ j ] = buffer[ i ];
+				j += inc;
+			}
+			UnlockBufferCF( ref buffer );
+		}
+
+		private static void	LinearFFT_Quick( ComplexF[] data, int start, int inc, int length, FourierDirection direction ) {
+			/*Debug.Assert( data != null );
+			Debug.Assert( start >= 0 );
+			Debug.Assert( inc >= 1 );
+			Debug.Assert( length >= 1 );
+			Debug.Assert( ( start + inc * ( length - 1 ) ) < data.Length );	*/
+			
+			// copy to buffer
+			ComplexF[]	buffer = null;
+			LockBufferCF( length, ref buffer );
+			int j = start;
+			for( int i = 0; i < length; i ++ ) {
+				buffer[ i ] = data[ j ];
+				j += inc;
+			}
+
+			FFT( buffer, length, direction );
+
+			// copy from buffer
+			j = start;
+			for( int i = 0; i < length; i ++ ) {
+				data[ j ] = buffer[ i ];
+				j += inc;
+			}
+			UnlockBufferCF( ref buffer );
+		}
+
+		//======================================================================================
+		//======================================================================================
+		
+		static private bool			_bufferCLocked	= false;
+		static private Complex[]	_bufferC		= new Complex[ 0 ];
+
+		static private void		LockBufferC( int length, ref Complex[] buffer ) {
+			Debug.Assert( length >= 0 );
+			Debug.Assert( _bufferCLocked == false );
+			
+			_bufferCLocked = true;
+			if( length >= _bufferC.Length ) {
+				_bufferC	= new Complex[ length ];
+			}
+			buffer =	_bufferC;
+		}
+		static private void		UnlockBufferC( ref Complex[] buffer ) {
+			Debug.Assert( _bufferC == buffer );
+			Debug.Assert( _bufferCLocked == true );
+			
+			_bufferCLocked = false;
+			buffer = null;
+		}
+
+		private static void	LinearFFT( Complex[] data, int start, int inc, int length, FourierDirection direction ) {
+			Debug.Assert( data != null );
+			Debug.Assert( start >= 0 );
+			Debug.Assert( inc >= 1 );
+			Debug.Assert( length >= 1 );
+			Debug.Assert( ( start + inc * ( length - 1 ) ) < data.Length );
+			
+			// copy to buffer
+			Complex[]	buffer = null;
+			LockBufferC( length, ref buffer );
+			int j = start;
+			for( int i = 0; i < length; i ++ ) {
+				buffer[ i ] = data[ j ];
+				j += inc;
+			}
+
+			FFT( buffer, length, direction );
+
+			// copy from buffer
+			j = start;
+			for( int i = 0; i < length; i ++ ) {
+				data[ j ] = buffer[ i ];
+				j += inc;
+			}
+			UnlockBufferC( ref buffer );
+		}
+
+		private static void	LinearFFT_Quick( Complex[] data, int start, int inc, int length, FourierDirection direction ) {
+			/*Debug.Assert( data != null );
+			Debug.Assert( start >= 0 );
+			Debug.Assert( inc >= 1 );
+			Debug.Assert( length >= 1 );
+			Debug.Assert( ( start + inc * ( length - 1 ) ) < data.Length );*/
+			
+			// copy to buffer
+			Complex[]	buffer = null;
+			LockBufferC( length, ref buffer );
+			int j = start;
+			for( int i = 0; i < length; i ++ ) {
+				buffer[ i ] = data[ j ];
+				j += inc;
+			}
+
+			FFT_Quick( buffer, length, direction );
+
+			// copy from buffer
+			j = start;
+			for( int i = 0; i < length; i ++ ) {
+				data[ j ] = buffer[ i ];
+				j += inc;
+			}
+			UnlockBufferC( ref buffer );
+		}
+
+		//======================================================================================
+		//======================================================================================
+
+		/// <summary>
+		/// Compute a 1D fast Fourier transform of a dataset of complex numbers (as pairs of float's).
+		/// </summary>
+		/// <param name="data"></param>
+		/// <param name="length"></param>
+		/// <param name="direction"></param>
+		public static void	FFT( float[] data, int length, FourierDirection direction ) {
+			Debug.Assert( data != null );
+			Debug.Assert( data.Length >= length*2 );
+			Debug.Assert( Fourier.IsPowerOf2( length ) == true );
+
+			Fourier.SyncLookupTableLength( length );
+			
+			int ln = Fourier.Log2( length );
+
+			// reorder array
+			Fourier.ReorderArray( data );
+
+			// successive doubling
+			int N = 1;
+			int signIndex = ( direction == FourierDirection.Forward ) ? 0 : 1;
+			for( int level = 1; level <= ln; level ++ ) {
+				int M = N;
+				N <<= 1;
+
+				float[] uRLookup = _uRLookupF[ level, signIndex ];
+				float[] uILookup = _uILookupF[ level, signIndex ];
+
+				for( int j = 0; j < M; j ++ ) {
+					float uR = uRLookup[j];
+					float uI = uILookup[j];
+				
+					for( int evenT = j; evenT < length; evenT += N ) {
+						int even = evenT << 1;
+						int odd = ( evenT + M ) << 1;
+						
+						float r = data[ odd ];
+						float i = data[ odd+1 ];
+
+						float odduR = r * uR - i * uI;
+						float odduI = r * uI + i * uR;
+
+						r = data[ even ];
+						i = data[ even+1 ];
+
+						data[ even ]	= r + odduR;
+						data[ even+1 ]	= i + odduI;
+
+						data[ odd ]		= r - odduR;
+						data[ odd+1 ]	= i - odduI;
+					}
+				}
+			}
+		}
+		
+		/// <summary>
+		/// Compute a 1D fast Fourier transform of a dataset of complex numbers (as pairs of float's).
+		/// </summary>
+		/// <param name="data"></param>
+		/// <param name="length"></param>
+		/// <param name="direction"></param>
+		public static void	FFT_Quick( float[] data, int length, FourierDirection direction ) {
+			/*Debug.Assert( data != null );
+			Debug.Assert( data.Length >= length*2 );
+			Debug.Assert( Fourier.IsPowerOf2( length ) == true );
+
+			Fourier.SyncLookupTableLength( length );*/
+			
+			int ln = Fourier.Log2( length );
+
+			// reorder array
+			Fourier.ReorderArray( data );
+
+			// successive doubling
+			int N = 1;
+			int signIndex = ( direction == FourierDirection.Forward ) ? 0 : 1;
+			for( int level = 1; level <= ln; level ++ ) {
+				int M = N;
+				N <<= 1;
+
+				float[] uRLookup = _uRLookupF[ level, signIndex ];
+				float[] uILookup = _uILookupF[ level, signIndex ];
+
+				for( int j = 0; j < M; j ++ ) {
+					float uR = uRLookup[j];
+					float uI = uILookup[j];
+				
+					for( int evenT = j; evenT < length; evenT += N ) {
+						int even = evenT << 1;
+						int odd = ( evenT + M ) << 1;
+						
+						float r = data[ odd ];
+						float i = data[ odd+1 ];
+
+						float odduR = r * uR - i * uI;
+						float odduI = r * uI + i * uR;
+
+						r = data[ even ];
+						i = data[ even+1 ];
+
+						data[ even ]	= r + odduR;
+						data[ even+1 ]	= i + odduI;
+
+						data[ odd ]		= r - odduR;
+						data[ odd+1 ]	= i - odduI;
+					}
+				}
+			}
+		}
+
+		/// <summary>
+		/// Compute a 1D fast Fourier transform of a dataset of complex numbers.
+		/// </summary>
+		/// <param name="data"></param>
+		/// <param name="length"></param>
+		/// <param name="direction"></param>
+		public static void	FFT( ComplexF[] data, int length, FourierDirection direction ) {
+			if( data == null ) {
+				throw new ArgumentNullException( "data" );
+			}
+			if( data.Length < length ) {
+				throw new ArgumentOutOfRangeException( "length", length, "must be at least as large as 'data.Length' parameter" );
+			}
+			if( Fourier.IsPowerOf2( length ) == false ) {
+				throw new ArgumentOutOfRangeException( "length", length, "must be a power of 2" );
+			}
+
+			Fourier.SyncLookupTableLength( length );
+
+			int ln = Fourier.Log2( length );
+			
+			// reorder array
+			Fourier.ReorderArray( data );
+			
+			// successive doubling
+			int N = 1;
+			int signIndex = ( direction == FourierDirection.Forward ) ? 0 : 1;
+			
+			for( int level = 1; level <= ln; level ++ ) {
+				int M = N;
+				N <<= 1;
+
+				float[] uRLookup = _uRLookupF[ level, signIndex ];
+				float[] uILookup = _uILookupF[ level, signIndex ];
+
+				for( int j = 0; j < M; j ++ ) {
+					float uR = uRLookup[j];
+					float uI = uILookup[j];
+
+					for( int even = j; even < length; even += N ) {
+						int odd	 = even + M;
+						
+						float	r = data[ odd ].Re;
+						float	i = data[ odd ].Im;
+
+						float	odduR = r * uR - i * uI;
+						float	odduI = r * uI + i * uR;
+
+						r = data[ even ].Re;
+						i = data[ even ].Im;
+						
+						data[ even ].Re	= r + odduR;
+						data[ even ].Im	= i + odduI;
+						
+						data[ odd ].Re	= r - odduR;
+						data[ odd ].Im	= i - odduI;
+					}
+				}
+			}
+
+		}
+
+		/// <summary>
+		/// Compute a 1D fast Fourier transform of a dataset of complex numbers.
+		/// </summary>
+		/// <param name="data"></param>
+		/// <param name="length"></param>
+		/// <param name="direction"></param>
+		public static void	FFT_Quick( ComplexF[] data, int length, FourierDirection direction ) {
+			/*if( data == null ) {
+				throw new ArgumentNullException( "data" );
+			}
+			if( data.Length < length ) {
+				throw new ArgumentOutOfRangeException( "length", length, "must be at least as large as 'data.Length' parameter" );
+			}
+			if( Fourier.IsPowerOf2( length ) == false ) {
+				throw new ArgumentOutOfRangeException( "length", length, "must be a power of 2" );
+			}
+
+			Fourier.SyncLookupTableLength( length );*/
+
+			int ln = Fourier.Log2( length );
+			
+			// reorder array
+			Fourier.ReorderArray( data );
+			
+			// successive doubling
+			int N = 1;
+			int signIndex = ( direction == FourierDirection.Forward ) ? 0 : 1;
+			
+			for( int level = 1; level <= ln; level ++ ) {
+				int M = N;
+				N <<= 1;
+
+				float[] uRLookup = _uRLookupF[ level, signIndex ];
+				float[] uILookup = _uILookupF[ level, signIndex ];
+
+				for( int j = 0; j < M; j ++ ) {
+					float uR = uRLookup[j];
+					float uI = uILookup[j];
+
+					for( int even = j; even < length; even += N ) {
+						int odd	 = even + M;
+						
+						float	r = data[ odd ].Re;
+						float	i = data[ odd ].Im;
+
+						float	odduR = r * uR - i * uI;
+						float	odduI = r * uI + i * uR;
+
+						r = data[ even ].Re;
+						i = data[ even ].Im;
+						
+						data[ even ].Re	= r + odduR;
+						data[ even ].Im	= i + odduI;
+						
+						data[ odd ].Re	= r - odduR;
+						data[ odd ].Im	= i - odduI;
+					}
+				}
+			}
+
+		}
+
+		/// <summary>
+		/// Compute a 1D fast Fourier transform of a dataset of complex numbers.
+		/// </summary>
+		/// <param name="data"></param>
+		/// <param name="direction"></param>
+		public static void	FFT( ComplexF[] data, FourierDirection direction ) {
+			if( data == null ) {
+				throw new ArgumentNullException( "data" );
+			}
+			Fourier.FFT( data, data.Length, direction );
+		}
+		
+		/// <summary>
+		/// Compute a 1D fast Fourier transform of a dataset of complex numbers.
+		/// </summary>
+		/// <param name="data"></param>
+		/// <param name="length"></param>
+		/// <param name="direction"></param>
+		public static void	FFT( Complex[] data, int length, FourierDirection direction ) {
+			if( data == null ) {
+				throw new ArgumentNullException( "data" );
+			}
+			if( data.Length < length ) {
+				throw new ArgumentOutOfRangeException( "length", length, "must be at least as large as 'data.Length' parameter" );
+			}
+			if( Fourier.IsPowerOf2( length ) == false ) {
+				throw new ArgumentOutOfRangeException( "length", length, "must be a power of 2" );
+			}
+
+			Fourier.SyncLookupTableLength( length );
+
+			int ln = Fourier.Log2( length );
+			
+			// reorder array
+			Fourier.ReorderArray( data );
+			
+			// successive doubling
+			int N = 1;
+			int signIndex = ( direction == FourierDirection.Forward ) ? 0 : 1;
+			
+			for( int level = 1; level <= ln; level ++ ) {
+				int M = N;
+				N <<= 1;
+
+				double[] uRLookup = _uRLookup[ level, signIndex ];
+				double[] uILookup = _uILookup[ level, signIndex ];
+
+				for( int j = 0; j < M; j ++ ) {
+					double uR = uRLookup[j];
+					double uI = uILookup[j];
+
+					for( int even = j; even < length; even += N ) {
+						int odd	 = even + M;
+						
+						double	r = data[ odd ].Re;
+						double	i = data[ odd ].Im;
+
+						double	odduR = r * uR - i * uI;
+						double	odduI = r * uI + i * uR;
+
+						r = data[ even ].Re;
+						i = data[ even ].Im;
+						
+						data[ even ].Re	= r + odduR;
+						data[ even ].Im	= i + odduI;
+						
+						data[ odd ].Re	= r - odduR;
+						data[ odd ].Im	= i - odduI;
+					}
+				}
+			}
+
+		}
+		
+		/// <summary>
+		/// Compute a 1D fast Fourier transform of a dataset of complex numbers.
+		/// </summary>
+		/// <param name="data"></param>
+		/// <param name="length"></param>
+		/// <param name="direction"></param>
+		public static void	FFT_Quick( Complex[] data, int length, FourierDirection direction ) {
+			/*if( data == null ) {
+				throw new ArgumentNullException( "data" );
+			}
+			if( data.Length < length ) {
+				throw new ArgumentOutOfRangeException( "length", length, "must be at least as large as 'data.Length' parameter" );
+			}
+			if( Fourier.IsPowerOf2( length ) == false ) {
+				throw new ArgumentOutOfRangeException( "length", length, "must be a power of 2" );
+			}
+
+			Fourier.SyncLookupTableLength( length );   */
+
+			int ln = Fourier.Log2( length );
+			
+			// reorder array
+			Fourier.ReorderArray( data );
+			
+			// successive doubling
+			int N = 1;
+			int signIndex = ( direction == FourierDirection.Forward ) ? 0 : 1;
+			
+			for( int level = 1; level <= ln; level ++ ) {
+				int M = N;
+				N <<= 1;
+
+				double[] uRLookup = _uRLookup[ level, signIndex ];
+				double[] uILookup = _uILookup[ level, signIndex ];
+
+				for( int j = 0; j < M; j ++ ) {
+					double uR = uRLookup[j];
+					double uI = uILookup[j];
+
+					for( int even = j; even < length; even += N ) {
+						int odd	 = even + M;
+						
+						double	r = data[ odd ].Re;
+						double	i = data[ odd ].Im;
+
+						double	odduR = r * uR - i * uI;
+						double	odduI = r * uI + i * uR;
+
+						r = data[ even ].Re;
+						i = data[ even ].Im;
+						
+						data[ even ].Re	= r + odduR;
+						data[ even ].Im	= i + odduI;
+						
+						data[ odd ].Re	= r - odduR;
+						data[ odd ].Im	= i - odduI;
+					}
+				}
+			}
+
+		}
+
+		/// <summary>
+		/// Compute a 1D real-symmetric fast fourier transform.
+		/// </summary>
+		/// <param name="data"></param>
+		/// <param name="direction"></param>
+		public static void	RFFT( float[] data, FourierDirection direction ) {
+			if( data == null ) {
+				throw new ArgumentNullException( "data" );
+			}
+			Fourier.RFFT( data, data.Length, direction );
+		}
+		
+		/// <summary>
+		/// Compute a 1D real-symmetric fast fourier transform.
+		/// </summary>
+		/// <param name="data"></param>
+		/// <param name="length"></param>
+		/// <param name="direction"></param>
+		public static void	RFFT( float[] data, int length, FourierDirection direction ) {
+			if( data == null ) {
+				throw new ArgumentNullException( "data" );
+			}
+			if( data.Length < length ) {
+				throw new ArgumentOutOfRangeException( "length", length, "must be at least as large as 'data.Length' parameter" );
+			}
+			if( Fourier.IsPowerOf2( length ) == false ) {
+				throw new ArgumentOutOfRangeException( "length", length, "must be a power of 2" );
+			}
+
+			float	c1 = 0.5f, c2;
+			float	theta	= (float) Math.PI / (length/2);
+
+			if( direction == FourierDirection.Forward ) {
+				c2 = -0.5f;
+				FFT( data, length/2, direction );
+			}
+			else {
+				c2 = 0.5f;
+				theta = - theta;
+			}
+
+			float	wtemp = (float) Math.Sin( 0.5*theta );
+			float	wpr = -2 * wtemp*wtemp;
+			float	wpi	=(float)  Math.Sin( theta );
+			float	wr	= 1 + wpr;
+			float	wi	= wpi;
+
+			// do / undo packing
+			for( int i = 1; i < length/4; i ++ ) {
+				int a = 2*i;
+				int b = length - 2*i;
+				float	h1r	= c1 * ( data[ a ] + data[ b ] );
+				float	h1i	= c1 * ( data[ a+1 ] - data[ b+1 ] );
+				float	h2r	= -c2 * ( data[ a+1 ] + data[ b+1 ] );
+				float	h2i	= c2 * ( data[ a ] - data[ b ] );
+				data[ a ]	= h1r + wr*h2r - wi*h2i;
+				data[ a+1 ]	= h1i + wr*h2i + wi*h2r;
+				data[ b ]	= h1r - wr*h2r + wi*h2i;
+				data[ b+1 ]	= -h1i + wr*h2i + wi*h2r;
+				wr = (wtemp = wr) * wpr - wi * wpi + wr;
+				wi = wi * wpr + wtemp * wpi + wi;
+			}
+			
+			if( direction == FourierDirection.Forward ) {
+				float  hir = data[0];
+				data[0] = hir + data[1];
+				data[1] = hir - data[1];
+			}
+			else {
+				float  hir = data[0];
+				data[0] = c1 * ( hir + data[1] );
+				data[1] = c1 * ( hir - data[1] );
+				Fourier.FFT( data, length/2, direction );
+			}
+		}
+		
+		/// <summary>
+		/// Compute a 2D fast fourier transform on a data set of complex numbers (represented as pairs of floats)
+		/// </summary>
+		/// <param name="data"></param>
+		/// <param name="xLength"></param>
+		/// <param name="yLength"></param>
+		/// <param name="direction"></param>
+		public static void	FFT2( float[] data, int xLength, int yLength, FourierDirection direction ) {
+			if( data == null ) {
+				throw new ArgumentNullException( "data" );
+			}
+			if( data.Length < xLength*yLength*2 ) {
+				throw new ArgumentOutOfRangeException( "data.Length", data.Length, "must be at least as large as 'xLength * yLength * 2' parameter" );
+			}
+			if( Fourier.IsPowerOf2( xLength ) == false ) {
+				throw new ArgumentOutOfRangeException( "xLength", xLength, "must be a power of 2" );
+			}
+			if( Fourier.IsPowerOf2( yLength ) == false ) {
+				throw new ArgumentOutOfRangeException( "yLength", yLength, "must be a power of 2" );
+			}
+
+			int xInc = 1;
+			int yInc = xLength;
+
+			if( xLength > 1 ) {
+				Fourier.SyncLookupTableLength( xLength );
+				for( int y = 0; y < yLength; y ++ ) {
+					int xStart = y * yInc;
+					Fourier.LinearFFT_Quick( data, xStart, xInc, xLength, direction );
+				}
+			}
+			
+			if( yLength > 1 ) {
+				Fourier.SyncLookupTableLength( yLength );
+				for( int x = 0; x < xLength; x ++ ) {
+					int yStart = x * xInc;
+					Fourier.LinearFFT_Quick( data, yStart, yInc, yLength, direction );
+				}
+			}
+		}
+
+		/// <summary>
+		/// Compute a 2D fast fourier transform on a data set of complex numbers
+		/// </summary>
+		/// <param name="data"></param>
+		/// <param name="xLength"></param>
+		/// <param name="yLength"></param>
+		/// <param name="direction"></param>
+		public static void	FFT2( ComplexF[] data, int xLength, int yLength, FourierDirection direction ) {
+			if( data == null ) {
+				throw new ArgumentNullException( "data" );
+			}
+			if( data.Length < xLength*yLength ) {
+				throw new ArgumentOutOfRangeException( "data.Length", data.Length, "must be at least as large as 'xLength * yLength' parameter" );
+			}
+			if( Fourier.IsPowerOf2( xLength ) == false ) {
+				throw new ArgumentOutOfRangeException( "xLength", xLength, "must be a power of 2" );
+			}
+			if( Fourier.IsPowerOf2( yLength ) == false ) {
+				throw new ArgumentOutOfRangeException( "yLength", yLength, "must be a power of 2" );
+			}
+
+			int xInc = 1;
+			int yInc = xLength;
+
+			if( xLength > 1 ) {
+				Fourier.SyncLookupTableLength( xLength );
+				for( int y = 0; y < yLength; y ++ ) {
+					int xStart = y * yInc;
+					Fourier.LinearFFT_Quick( data, xStart, xInc, xLength, direction );
+				}
+			}
+			
+			if( yLength > 1 ) {
+				Fourier.SyncLookupTableLength( yLength );
+				for( int x = 0; x < xLength; x ++ ) {
+					int yStart = x * xInc;
+					Fourier.LinearFFT_Quick( data, yStart, yInc, yLength, direction );
+				}
+			}
+		}
+
+		/// <summary>
+		/// Compute a 2D fast fourier transform on a data set of complex numbers
+		/// </summary>
+		/// <param name="data"></param>
+		/// <param name="xLength"></param>
+		/// <param name="yLength"></param>
+		/// <param name="direction"></param>
+		public static void	FFT2( Complex[] data, int xLength, int yLength, FourierDirection direction ) {
+			if( data == null ) {
+				throw new ArgumentNullException( "data" );
+			}
+			if( data.Length < xLength*yLength ) {
+				throw new ArgumentOutOfRangeException( "data.Length", data.Length, "must be at least as large as 'xLength * yLength' parameter" );
+			}
+			if( Fourier.IsPowerOf2( xLength ) == false ) {
+				throw new ArgumentOutOfRangeException( "xLength", xLength, "must be a power of 2" );
+			}
+			if( Fourier.IsPowerOf2( yLength ) == false ) {
+				throw new ArgumentOutOfRangeException( "yLength", yLength, "must be a power of 2" );
+			}
+
+			int xInc = 1;
+			int yInc = xLength;
+
+			if( xLength > 1 ) {
+				Fourier.SyncLookupTableLength( xLength );
+				for( int y = 0; y < yLength; y ++ ) {
+					int xStart = y * yInc;
+					Fourier.LinearFFT_Quick( data, xStart, xInc, xLength, direction );
+				}
+			}
+			
+			if( yLength > 1 ) {
+				Fourier.SyncLookupTableLength( yLength );
+				for( int x = 0; x < xLength; x ++ ) {
+					int yStart = x * xInc;
+					Fourier.LinearFFT_Quick( data, yStart, yInc, yLength, direction );
+				}
+			}
+		}
+
+		/// <summary>
+		/// Compute a 3D fast fourier transform on a data set of complex numbers
+		/// </summary>
+		/// <param name="data"></param>
+		/// <param name="xLength"></param>
+		/// <param name="yLength"></param>
+		/// <param name="zLength"></param>
+		/// <param name="direction"></param>
+		public static void	FFT3( ComplexF[] data, int xLength, int yLength, int zLength, FourierDirection direction ) {
+			if( data == null ) {
+				throw new ArgumentNullException( "data" );
+			}
+			if( data.Length < xLength*yLength*zLength ) {
+				throw new ArgumentOutOfRangeException( "data.Length", data.Length, "must be at least as large as 'xLength * yLength * zLength' parameter" );
+			}
+			if( Fourier.IsPowerOf2( xLength ) == false ) {
+				throw new ArgumentOutOfRangeException( "xLength", xLength, "must be a power of 2" );
+			}
+			if( Fourier.IsPowerOf2( yLength ) == false ) {
+				throw new ArgumentOutOfRangeException( "yLength", yLength, "must be a power of 2" );
+			}
+			if( Fourier.IsPowerOf2( zLength ) == false ) {
+				throw new ArgumentOutOfRangeException( "zLength", zLength, "must be a power of 2" );
+			}
+
+			int xInc = 1;
+			int yInc = xLength;
+			int zInc = xLength * yLength;
+
+			if( xLength > 1 ) {
+				Fourier.SyncLookupTableLength( xLength );
+				for( int z = 0; z < zLength; z ++ ) {
+					for( int y = 0; y < yLength; y ++ ) {
+						int xStart = y * yInc + z * zInc;
+						Fourier.LinearFFT_Quick( data, xStart, xInc, xLength, direction );
+					}
+				}
+			}
+			
+			if( yLength > 1 ) {
+				Fourier.SyncLookupTableLength( yLength );
+				for( int z = 0; z < zLength; z ++ ) {
+					for( int x = 0; x < xLength; x ++ ) {
+						int yStart = z * zInc + x * xInc;
+						Fourier.LinearFFT_Quick( data, yStart, yInc, yLength, direction );
+					}
+				}
+			}
+			
+			if( zLength > 1 ) {
+				Fourier.SyncLookupTableLength( zLength );
+				for( int y = 0; y < yLength; y ++ ) {
+					for( int x = 0; x < xLength; x ++ ) {
+						int zStart = y * yInc + x * xInc;
+						Fourier.LinearFFT_Quick( data, zStart, zInc, zLength, direction );
+					}
+				}
+			}
+		}
+
+		/// <summary>
+		/// Compute a 3D fast fourier transform on a data set of complex numbers
+		/// </summary>
+		/// <param name="data"></param>
+		/// <param name="xLength"></param>
+		/// <param name="yLength"></param>
+		/// <param name="zLength"></param>
+		/// <param name="direction"></param>
+		public static void	FFT3( Complex[] data, int xLength, int yLength, int zLength, FourierDirection direction ) {
+			if( data == null ) {
+				throw new ArgumentNullException( "data" );
+			}
+			if( data.Length < xLength*yLength*zLength ) {
+				throw new ArgumentOutOfRangeException( "data.Length", data.Length, "must be at least as large as 'xLength * yLength * zLength' parameter" );
+			}
+			if( Fourier.IsPowerOf2( xLength ) == false ) {
+				throw new ArgumentOutOfRangeException( "xLength", xLength, "must be a power of 2" );
+			}
+			if( Fourier.IsPowerOf2( yLength ) == false ) {
+				throw new ArgumentOutOfRangeException( "yLength", yLength, "must be a power of 2" );
+			}
+			if( Fourier.IsPowerOf2( zLength ) == false ) {
+				throw new ArgumentOutOfRangeException( "zLength", zLength, "must be a power of 2" );
+			}
+
+			int xInc = 1;
+			int yInc = xLength;
+			int zInc = xLength * yLength;
+
+			if( xLength > 1 ) {
+				Fourier.SyncLookupTableLength( xLength );
+				for( int z = 0; z < zLength; z ++ ) {
+					for( int y = 0; y < yLength; y ++ ) {
+						int xStart = y * yInc + z * zInc;
+						Fourier.LinearFFT_Quick( data, xStart, xInc, xLength, direction );
+					}
+				}
+			}
+			
+			if( yLength > 1 ) {
+				Fourier.SyncLookupTableLength( yLength );
+				for( int z = 0; z < zLength; z ++ ) {
+					for( int x = 0; x < xLength; x ++ ) {
+						int yStart = z * zInc + x * xInc;
+						Fourier.LinearFFT_Quick( data, yStart, yInc, yLength, direction );
+					}
+				}
+			}
+			
+			if( zLength > 1 ) {
+				Fourier.SyncLookupTableLength( zLength );
+				for( int y = 0; y < yLength; y ++ ) {
+					for( int x = 0; x < xLength; x ++ ) {
+						int zStart = y * yInc + x * xInc;
+						Fourier.LinearFFT_Quick( data, zStart, zInc, zLength, direction );
+					}
+				}
+			}
+		}
+		
+	}
+}

+ 55 - 0
mcs/class/System.Drawing/Test/DrawingTest/Exocortex.DSP/src/FourierDirection.cs

@@ -0,0 +1,55 @@
+/*
+ * BSD Licence:
+ * Copyright (c) 2001, 2002 Ben Houston [ [email protected] ]
+ * Exocortex Technologies [ www.exocortex.org ]
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ * notice, this list of conditions and the following disclaimer in the 
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+
+using System;
+
+namespace Exocortex.DSP
+{
+	// Comments? Questions? Bugs? Tell Ben Houston at [email protected]
+	// Version: May 4, 2002
+
+	/// <summary>
+	/// <p>The direction of the fourier transform.</p>
+	/// </summary>
+	public enum FourierDirection : int {
+		/// <summary>
+		/// Forward direction.  Usually in reference to moving from temporal
+		/// representation to frequency representation
+		/// </summary>
+		Forward = 1,
+		/// <summary>
+		/// Backward direction. Usually in reference to moving from frequency
+		/// representation to temporal representation
+		/// </summary>
+		Backward = -1,
+	}
+}

+ 58 - 0
mcs/class/System.Drawing/Test/DrawingTest/Test/AssemblyInfo.cs

@@ -0,0 +1,58 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]		
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the 
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing. 
+//
+// Notes: 
+//   (*) If no key is specified, the assembly is not signed.
+//   (*) KeyName refers to a key that has been installed in the Crypto Service
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains
+//       a key.
+//   (*) If the KeyFile and the KeyName values are both specified, the 
+//       following processing occurs:
+//       (1) If the KeyName can be found in the CSP, that key is used.
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key 
+//           in the KeyFile is installed into the CSP and used.
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+//       When specifying the KeyFile, the location of the KeyFile should be
+//       relative to the project output directory which is
+//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+//       located in the project directory, you would specify the AssemblyKeyFile 
+//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+//       documentation for more information on this.
+//
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]

+ 51 - 0
mcs/class/System.Drawing/Test/DrawingTest/Test/Bitmap.cs

@@ -0,0 +1,51 @@
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using NUnit.Framework;
+using DrawingTestHelper;
+
+namespace Test.Sys.Drawing
+{
+	/// <summary>
+	/// Summary description for Bitmap.
+	/// </summary>
+	[TestFixture]
+	public class BitmapFixture {
+		DrawingTest t;
+
+		[SetUp]
+		public void SetUp () {
+			t = DrawingTest.Create (64, 64);
+			Bitmap b = new Bitmap (@"..\..\..\Test\Bitmap1.png");
+			t.Graphics.DrawImageUnscaled (b, 0, 0);
+		}
+		[Test]
+		public void CloneTest () {
+			Bitmap b1 = (Bitmap) t.Bitmap.Clone ();
+			Assert.IsFalse (Object.ReferenceEquals (t.Bitmap, b1));
+			Assert.AreEqual (DrawingTest.CalculateNorm (t.Bitmap),
+				DrawingTest.CalculateNorm (b1));
+			t.Graphics.FillRectangle (Brushes.Black, 0, 0, 64, 64);
+			Assert.IsFalse (DrawingTest.CalculateNorm (t.Bitmap) ==
+				DrawingTest.CalculateNorm (b1));
+		}
+		[Test]
+		public void GetPixel () {
+			Assert.AreEqual (Color.FromArgb (255, Color.White),
+				t.Bitmap.GetPixel (0, 0));
+			t.Graphics.FillRectangle (Brushes.Black, 30, 30, 30, 30);
+			Assert.AreEqual (Color.FromArgb (255, Color.Black),
+				t.Bitmap.GetPixel (31, 31));
+		}
+		[Test]
+		public void MakeTransparent () {
+			t.Show ();
+			Bitmap b = (Bitmap) t.Bitmap.Clone ();
+			b.MakeTransparent (Color.White);
+			t.Graphics.FillRectangle (Brushes.Black, 0, 0, 64, 64);
+			t.Graphics.DrawImageUnscaled (b, 0, 0);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+		}
+	}
+}

BIN
mcs/class/System.Drawing/Test/DrawingTest/Test/Bitmap1.png


+ 31 - 0
mcs/class/System.Drawing/Test/DrawingTest/Test/Brush.cs

@@ -0,0 +1,31 @@
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using NUnit.Framework;
+using DrawingTestHelper;
+
+namespace Test.Sys.Drawing
+{
+	/// <summary>
+	/// Summary description for Brush.
+	/// </summary>
+	[TestFixture]
+	public class BrushFixture
+	{
+		[Test]
+		public void ColorTest()
+		{
+			SolidBrush b = new SolidBrush (Color.Azure);
+			Assert.AreEqual (Color.Azure, b.Color);
+			DrawingTest t = DrawingTest.Create (64, 64);
+			t.Graphics.FillRectangle (b, 0, 0, 30, 30);
+			t.Show ();
+			b.Color = Color.FromArgb (100, 240, 30);
+			t.Graphics.FillRectangle (b, 30, 5, 30, 50);
+			t.Show ();
+			b.Color = Color.FromArgb (70, Color.FromName ("red"));
+			t.Graphics.FillRectangle (b, 15, 15, 40, 40);
+			t.Show ();
+		}
+	}
+}

+ 1951 - 0
mcs/class/System.Drawing/Test/DrawingTest/Test/Graphics.cs

@@ -0,0 +1,1951 @@
+//
+// Test.System.Drawing.Graphics.cs
+//
+// Author:
+//   Konstantin Triger <[email protected]>
+//
+
+//
+// Copyright (C) 2005 Mainsoft, Corp (http://www.mainsoft.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Diagnostics;
+using NUnit.Framework;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Text;
+using System.Drawing.Imaging;
+using DrawingTestHelper;
+using System.IO;
+
+namespace Test.Sys.Drawing.GraphicsFixtures
+{
+	#region GraphicsFixtureProps
+
+	[TestFixture]
+	public class GraphicsFixtureProps {
+
+		protected DrawingTest t;
+		const int TOLERANCE = 3; //in %
+
+		[SetUp]
+		public void SetUp() {
+			t = DrawingTest.Create(512, 512);
+		}
+
+		[Test]
+		public void ClipTest() {
+			Region r = new Region();
+			Assert.IsTrue(r.Equals(t.Graphics.Clip, t.Graphics));
+
+			r = new Region(new Rectangle(10, 10, 60, 60));
+			t.Graphics.Clip = r;
+			Assert.IsTrue(r.Equals(t.Graphics.Clip, t.Graphics));
+
+			Pen redPen   = new Pen(Color.Red, 3);
+			Pen greenPen = new Pen(Color.Green, 3);
+			// Create points that define curve.
+			Point point1 = new Point( 50,  50);
+			Point point2 = new Point(100,  25);
+			Point point3 = new Point(200,   5);
+			Point point4 = new Point(250,  50);
+			Point point5 = new Point(300, 100);
+			Point point6 = new Point(350, 200);
+			Point point7 = new Point(250, 250);
+			Point[] curvePoints = {
+									  point1,
+									  point2,
+									  point3,
+									  point4,
+									  point5,
+									  point6,
+									  point7
+								  };
+			// Draw lines between original points to screen.
+			t.Graphics.DrawLines(redPen, curvePoints);
+			t.Show ();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void ClipBoundsTest() {
+			//Debugger.Launch();
+			Region r = new Region();
+			Assert.IsTrue(t.Graphics.ClipBounds.Equals(r.GetBounds(t.Graphics)));
+
+			RectangleF rf = new RectangleF(10, 10, 60, 60);
+			r = new Region(rf);
+			t.Graphics.Clip = r;
+			Assert.IsTrue(rf.Equals(t.Graphics.ClipBounds));
+		}
+
+		[Test]
+		public void CompositingModeTest() {
+			//TODO: seems to draw equal images
+			Assert.AreEqual(CompositingMode.SourceOver, t.Graphics.CompositingMode);
+
+			Bitmap b = new Bitmap(100, 100);
+			Graphics g = Graphics.FromImage(b);
+
+			Color c = Color.FromArgb(100, Color.Red);
+
+			Brush redBrush = new SolidBrush(c);
+			g.FillEllipse(redBrush, 5, 6, 100, 200);
+			//t.Graphics.FillEllipse(redBrush, 5, 6, 100, 200);
+			t.Graphics.DrawImage(b, 10, 10);
+
+			t.Show ();
+
+			t.Graphics.CompositingMode = CompositingMode.SourceCopy;
+			
+			t.Graphics.DrawImage(b, 300, 300);
+
+			t.Show ();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test] //TBD
+		public void CompositingQualityTest() {
+		}
+
+		[Test]
+		public void DpiXTest() {
+			Assert.IsTrue(t.Graphics.DpiX == 96f);
+		}
+
+		[Test]
+		public void DpiYTest() {
+			Assert.IsTrue(t.Graphics.DpiY == 96f);
+		}
+
+		[Test] //TBD
+		public void InterpolationModeTest() {
+		}
+
+		[Test]
+		public void IsClipEmtpyTest() {
+			Assert.IsFalse(t.Graphics.IsClipEmpty);
+
+			try {
+				t.Graphics.Clip = null;
+				Assert.Fail("The ArgumentNullException was not thrown");
+			}
+			catch(Exception e) {
+				Assert.AreEqual(e.GetType(), typeof(ArgumentNullException));
+			}
+
+			Region r = new Region(new Rectangle(10, 10, 0, 0));
+			t.Graphics.Clip = r;
+
+			Assert.IsTrue( t.Graphics.IsClipEmpty);
+		}
+
+		[Test]
+		public void IsVisibleClipEmtpyTest() {
+			Assert.IsFalse(t.Graphics.IsVisibleClipEmpty, "default t.Graphics.IsVisibleClipEmpty");
+
+			Region r = new Region(new Rectangle(512, 512, 100, 100));
+			t.Graphics.Clip = r;
+			Assert.IsFalse(t.Graphics.IsClipEmpty);
+			Assert.IsTrue(t.Graphics.IsVisibleClipEmpty);
+		}
+
+		[Test]
+		public void PageScaleTest() {
+			Assert.AreEqual(1f, t.Graphics.PageScale);
+		}
+
+		[Test]
+		public void PageUnitTest() {
+			Assert.AreEqual(GraphicsUnit.Display, t.Graphics.PageUnit);
+		}
+
+		[Test]
+		public void PixelOffsetModeTest() {
+			Assert.AreEqual(PixelOffsetMode.Default, t.Graphics.PixelOffsetMode);
+		}
+
+		[Test]
+		public void RenderingOriginTest() {
+			Assert.AreEqual(new Point(0,0), t.Graphics.RenderingOrigin);
+		}
+
+		[Test]
+		public void SmoothingModeTest() {
+			Assert.AreEqual(SmoothingMode.None, t.Graphics.SmoothingMode);
+		}
+
+		[Test]
+		public void TextContrastTest() {
+			Assert.AreEqual(4, t.Graphics.TextContrast);
+		}
+
+		[Test]
+		public void TextRenderingHintTest() {
+			Assert.AreEqual(TextRenderingHint.SystemDefault, t.Graphics.TextRenderingHint);
+		}
+
+		[Test]
+		public void TransformTest() {
+			Assert.AreEqual(new Matrix(), t.Graphics.Transform);
+		}
+
+		[Test]
+		public void VisibleClipBoundsTest() {
+			Assert.AreEqual(new RectangleF(0, 0, 512, 512), t.Graphics.VisibleClipBounds);
+		}
+	}
+
+	#endregion
+
+	#region GraphicsFixture
+	/// <summary>
+	/// Summary description for Graphics.
+	/// </summary>
+	[TestFixture]
+	public class GraphicsFixture
+	{
+		protected DrawingTest t;
+		const int TOLERANCE = 3; //in %
+
+		[SetUp]
+		public virtual void SetUp() {
+			t = DrawingTest.Create(512, 512);
+		}
+
+		[TearDown]
+		public void TearDown() {
+		}
+
+		[Test]
+		public void BeginContainerTest() {
+			// Define transformation for container.
+			RectangleF srcRect = new RectangleF(0.0F, 0.0F, 200.0F, 200.0F);
+			RectangleF destRect = new RectangleF(100.0F, 100.0F, 150.0F, 150.0F);
+			// Begin graphics container.
+			GraphicsContainer containerState = t.Graphics.BeginContainer(
+				destRect, srcRect,
+				GraphicsUnit.Pixel);
+			// Fill red rectangle in container.
+			t.Graphics.FillRectangle(new SolidBrush(Color.Red), 0.0F, 0.0F, 200.0F, 200.0F);
+			t.Show ();
+			// End graphics container.
+			t.Graphics.EndContainer(containerState);
+			// Fill untransformed rectangle with green.
+			t.Graphics.FillRectangle(new SolidBrush(Color.Green), 0.0F, 0.0F, 200.0F, 200.0F);
+			t.Show ();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void ClearTest() {
+			// Clear screen with teal background.
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			t.Graphics.Clear(Color.Teal);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawArcTest(){
+			// Create pen.
+			Pen blackPen= new Pen(Color.Black, 1);
+			// Create coordinates of rectangle to bound ellipse.
+			float x = 10.0F;
+			float y = 10.0F;
+			float width = 400.0F;
+			float height = 100.0F;
+			// Create start and sweep angles on ellipse.
+			float startAngle =  370.0F;
+			float sweepAngle = 70.0F;
+			// Draw arc to screen.
+			t.Graphics.DrawArc(blackPen, (int)x, (int)y, (int)width, (int)height, (int)startAngle, (int)sweepAngle);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+			 startAngle =  10.0F;
+			 sweepAngle = 120.0F;
+			t.Graphics.DrawArc(blackPen, new Rectangle((int)x, (int)y, (int)width, (int)height), startAngle, sweepAngle);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+			 startAngle =  10.0F;
+			 sweepAngle = 190.0F;
+			t.Graphics.DrawArc(blackPen, x, y, width, height, startAngle, sweepAngle);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+			 startAngle =  10.0F;
+			 sweepAngle = 300.0F;
+			t.Graphics.DrawArc(blackPen, new RectangleF(x, y, width, height), startAngle, sweepAngle);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawBezierTest() {
+			// Create pen.
+			Pen blackPen = new Pen(Color.Black, 3);
+			// Create coordinates of points for curve.
+			float startX = 100.0F;
+			float startY = 100.0F;
+			float controlX1 = 200.0F;
+			float controlY1 =  10.0F;
+			float controlX2 = 350.0F;
+			float controlY2 =  50.0F;
+			float endX = 500.0F;
+			float endY = 100.0F;
+			// Draw arc to screen.
+			t.Graphics.DrawBezier(blackPen, startX, startY,
+				controlX1, controlY1,
+				controlX2, controlY2,
+				endX, endY);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+			t.Graphics.DrawBezier(blackPen, new PointF( startX, startY),
+				new PointF(controlX1, controlY1),
+				new PointF(controlX2, controlY2),
+				new PointF(endX, endY));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+			t.Graphics.DrawBezier(blackPen, new Point((int)startX, (int)startY),
+				new Point((int)controlX1, (int)controlY1),
+				new Point((int)controlX2, (int)controlY2),
+				new Point((int)endX, (int)endY));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawBeziersTest() {
+			// Create pen.
+			Pen blackPen = new Pen(Color.Black, 3);
+			// Create points for curve.
+			Point start = new Point(100, 100);
+			Point control1 = new Point(200, 10);
+			Point control2 = new Point(350, 50);
+			Point end1 = new Point(500, 100);
+			Point control3 = new Point(600, 150);
+			Point control4 = new Point(650, 250);
+			Point end2 = new Point(500, 300);
+			Point[] bezierPoints = {
+				start, control1, control2, end1,
+				control3, control4, end2
+			};
+			// Draw arc to screen.
+			t.Graphics.DrawBeziers(blackPen, bezierPoints);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			PointF startF = new PointF(100.0F, 100.0F);
+			PointF control1F = new PointF(200.0F, 10.0F);
+			PointF control2F = new PointF(350.0F, 50.0F);
+			PointF end1F = new PointF(500.0F, 100.0F);
+			PointF control3F = new PointF(600.0F, 150.0F);
+			PointF control4F = new PointF(650.0F, 250.0F);
+			PointF end2F = new PointF(500.0F, 300.0F);
+			PointF[] bezierPointsF = {
+										startF, control1F, control2F, end1F,
+										control3F, control4F, end2F
+									};
+			// Draw arc to screen.
+			t.Graphics.DrawBeziers(blackPen, bezierPointsF);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawClosedCurveTest(){
+			// Create pens.
+			Pen redPen   = new Pen(Color.Red, 3);
+			Pen greenPen = new Pen(Color.Green, 3);
+			// Create points that define curve.
+			PointF point1 = new PointF( 50.0F,  50.0F);
+			PointF point2 = new PointF(100.0F,  25.0F);
+			PointF point3 = new PointF(200.0F,   5.0F);
+			PointF point4 = new PointF(250.0F,  50.0F);
+			PointF point5 = new PointF(300.0F, 100.0F);
+			PointF point6 = new PointF(350.0F, 200.0F);
+			PointF point7 = new PointF(250.0F, 250.0F);
+			PointF[] curvePoints = {
+				point1,
+				point2,
+				point3,
+				point4,
+				point5,
+				point6,
+				point7
+			};
+			// Draw lines between original points to screen.
+			t.Graphics.DrawLines(redPen, curvePoints);
+			// Create tension and fill mode.
+			float tension = 0.7F;
+			FillMode aFillMode = FillMode.Alternate;
+			// Draw closed curve to screen.
+			t.Graphics.DrawClosedCurve(greenPen, curvePoints, tension, aFillMode);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			aFillMode = FillMode.Winding;
+			// Draw closed curve to screen.
+			t.Graphics.DrawClosedCurve(greenPen, curvePoints, tension, aFillMode);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawCurveTest() {
+			// Create pens.
+			Pen redPen   = new Pen(Color.Red, 3);
+			Pen greenPen = new Pen(Color.Green, 3);
+			// Create points that define curve.
+			Point point1 = new Point( 50,  50);
+			Point point2 = new Point(100,  25);
+			Point point3 = new Point(200,   5);
+			Point point4 = new Point(250,  50);
+			Point point5 = new Point(300, 100);
+			Point point6 = new Point(350, 200);
+			Point point7 = new Point(250, 250);
+			Point[] curvePoints = {
+				point1,
+				point2,
+				point3,
+				point4,
+				point5,
+				point6,
+				point7
+			};
+			// Draw lines between original points to screen.
+			t.Graphics.DrawLines(redPen, curvePoints);
+			// Create offset, number of segments, and tension.
+			int offset = 2;
+			int numSegments = 4;
+			float tension = 0.7F;
+			// Draw curve to screen.
+			t.Graphics.DrawCurve(greenPen, curvePoints, offset, numSegments, tension);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawCurve(greenPen, curvePoints, tension);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawCurve(greenPen, curvePoints);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawCurveTestF() {
+			// Create pens.
+			Pen redPen   = new Pen(Color.Red, 3);
+			Pen greenPen = new Pen(Color.Green, 3);
+			// Create points that define curve.
+			PointF point1 = new PointF( 50.0F,  50.0F);
+			PointF point2 = new PointF(100.0F,  25.0F);
+			PointF point3 = new PointF(200.0F,   5.0F);
+			PointF point4 = new PointF(250.0F,  50.0F);
+			PointF point5 = new PointF(300.0F, 100.0F);
+			PointF point6 = new PointF(350.0F, 200.0F);
+			PointF point7 = new PointF(250.0F, 250.0F);
+			PointF[] curvePoints = {
+									   point1,
+									   point2,
+									   point3,
+									   point4,
+									   point5,
+									   point6,
+									   point7
+								   };
+			// Draw lines between original points to screen.
+			t.Graphics.DrawLines(redPen, curvePoints);
+			// Create offset, number of segments, and tension.
+			int offset = 2;
+			int numSegments = 4;
+			float tension = 0.7F;
+			// Draw curve to screen.
+			t.Graphics.DrawCurve(greenPen, curvePoints, offset, numSegments, tension);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawCurve(greenPen, curvePoints, offset, numSegments);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawCurve(greenPen, curvePoints, tension);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawCurve(greenPen, curvePoints);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawEllipseTest() {
+			// Create pen.
+			Pen blackPen = new Pen(Color.Black, 3);
+			// Create location and size of ellipse.
+			int x = 0;
+			int y = 0;
+			int width = 200;
+			int height = 100;
+			// Draw ellipse to screen.
+			t.Graphics.DrawEllipse(blackPen, x, y, width, height);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawEllipse(blackPen, new Rectangle(x, y, width, height));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawEllipseTestF() {
+			// Create pen.
+			Pen blackPen = new Pen(Color.Black, 3);
+			// Create location and size of ellipse.
+			float x = 0.0F;
+			float y = 0.0F;
+			float width = 200.0F;
+			float height = 100.0F;
+			// Draw ellipse to screen.
+			t.Graphics.DrawEllipse(blackPen, x, y, width, height);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawEllipse(blackPen, new RectangleF(x, y, width, height));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		static string getInFile (string file) {
+			string sRslt;						
+			
+			sRslt = Path.GetFullPath (file);
+			
+			if (! File.Exists (file))
+				sRslt = Path.Combine (
+					Path.Combine ("..", ".."),
+					file);
+
+			return sRslt;
+		}
+
+		[Test]
+		public void DrawIconTest() {
+			// Create icon.
+			Icon newIcon = new Icon(getInFile ("SampIcon.ico"));
+			// Create coordinates for upper-left corner of icon.
+			int x = 100;
+			int y = 100;
+			// Draw icon to screen.
+			t.Graphics.DrawIcon(newIcon, x, y);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+
+			t.Graphics.DrawIcon(newIcon, new Rectangle(200, 300, 125, 345));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawIconUnstretchedTest() {
+			// Create icon.
+			Icon newIcon = new Icon(getInFile ("SampIcon.ico"));
+			// Create rectangle for icon.
+			Rectangle rect = new Rectangle( 100, 100, 200, 200);
+			// Draw icon to screen.
+			t.Graphics.DrawIconUnstretched(newIcon, rect);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+#if INTPTR_SUPPORTED
+		// Define DrawImageAbort callback method.
+		private bool DrawImageCallback(IntPtr callBackData) {
+			// Test for call that passes callBackData parameter.
+			if(callBackData==IntPtr.Zero) {
+				// If no callBackData passed, abort DrawImage method.
+				return true;
+			}
+			else {
+				// If callBackData passed, continue DrawImage method.
+				return false;
+			}
+		}
+		
+		[Test] //TBD: add more overrides
+		public void DrawImageTest() {
+			// Create callback method.
+			Graphics.DrawImageAbort imageCallback
+				= new Graphics.DrawImageAbort(DrawImageCallback);
+			IntPtr imageCallbackData = new IntPtr(1);
+			// Create image.
+			Image newImage = Image.FromFile("SampIcon.ico");
+			// Create rectangle for displaying original image.
+			Rectangle destRect1 = new Rectangle( 100, 25, 450, 150);
+			// Create coordinates of rectangle for source image.
+			float x = 50.0F;
+			float y = 50.0F;
+			float width = 150.0F;
+			float height = 150.0F;
+			GraphicsUnit units = GraphicsUnit.Pixel;
+			// Draw original image to screen.
+			t.Graphics.DrawImage(newImage, destRect1, x, y, width, height, units);
+			t.Show();
+			// Create rectangle for adjusted image.
+			Rectangle destRect2 = new Rectangle(100, 175, 450, 150);
+			// Create image attributes and set large gamma.
+			ImageAttributes imageAttr = new ImageAttributes();
+			imageAttr.SetGamma(4.0F);
+			// Draw adjusted image to screen.
+
+			t.Graphics.DrawImage(
+				newImage,
+				destRect2,
+				x, y,
+				width, height,
+				units,
+				imageAttr,
+				imageCallback,
+				imageCallbackData);
+
+			t.Show();
+		}
+#endif
+		[Test]
+		public void DrawImageUnscaledTest() {
+			// Create image.
+			Image newImage = Image.FromFile(getInFile ("SampIcon.ico"));
+			// Create coordinates for upper-left corner of image.
+			int x = 100;
+			int y = 100;
+			// Draw image to screen.
+			t.Graphics.DrawImageUnscaled(newImage, x, y, 100, 125);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawImageUnscaled(newImage, new Rectangle(x, y, 34, 235));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawImageUnscaled(newImage, x, y);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawImageUnscaled(newImage, new Point(x, y));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawLineTest() {
+			// Create pen.
+			Pen blackPen = new Pen(Color.Black, 3);
+			// Create coordinates of points that define line.
+			int x1 = 100;
+			int y1 = 100;
+			int x2 = 500;
+			int y2 = 100;
+			// Draw line to screen.
+			t.Graphics.DrawLine(blackPen, x1, y1, x2, y2);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawLine(blackPen, new Point( x1, y1), new Point( x2, y2));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawLineTestF() {
+			// Create pen.
+			Pen blackPen = new Pen(Color.Black, 3);
+			// Create coordinates of points that define line.
+			float x1 = 100.0F;
+			float y1 = 100.0F;
+			float x2 = 500.0F;
+			float y2 = 100.0F;
+			// Draw line to screen.
+			t.Graphics.DrawLine(blackPen, x1, y1, x2, y2);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawLine(blackPen, new PointF( x1, y1), new PointF( x2, y2));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawLinesTest() {
+			// Create pen.
+			Pen pen = new Pen(Color.Black, 3);
+			// Create array of points that define lines to draw.
+			Point[] points = {
+				new Point( 10,  10),
+				new Point( 10, 100),
+				new Point(200,  50),
+				new Point(250, 300)
+			};
+			//Draw lines to screen.
+			t.Graphics.DrawLines(pen, points);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawLinesTestF() {
+			// Create pen.
+			Pen pen = new Pen(Color.Black, 3);
+			// Create array of points that define lines to draw.
+			PointF[] points = {
+								  new PointF( 10.0F,  10.0F),
+								  new PointF( 10.0F, 100.0F),
+								  new PointF(200.0F,  50.0F),
+								  new PointF(250.0F, 300.0F)
+							  };
+			//Draw lines to screen.
+			t.Graphics.DrawLines(pen, points);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawPathTest() {
+			// Create graphics path object and add ellipse.
+			GraphicsPath graphPath = new GraphicsPath();
+			graphPath.AddEllipse(0, 0, 200, 100);
+			// Create pen.
+			Pen blackPen = new Pen(Color.Black, 3);
+			// Draw graphics path to screen.
+			t.Graphics.DrawPath(blackPen, graphPath);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawPieTestF() {
+			// Create pen.
+			Pen blackPen = new Pen(Color.Black, 3);
+			// Create location and size of ellipse.
+			float x = 0.0F;
+			float y = 0.0F;
+			float width = 200.0F;
+			float height = 100.0F;
+			// Create start and sweep angles.
+			float startAngle =  0.0F;
+			float sweepAngle = 45.0F;
+			// Draw pie to screen.
+			t.Graphics.DrawPie(blackPen, x, y, width, height, startAngle, sweepAngle);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawPie(blackPen, new RectangleF( x, y, width, height), startAngle, sweepAngle);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawPieTest() {
+			// Create pen.
+			Pen blackPen = new Pen(Color.Black, 3);
+			// Create location and size of ellipse.
+			int x = 0;
+			int y = 0;
+			int width = 200;
+			int height = 100;
+			// Create start and sweep angles.
+			int startAngle =  0;
+			int sweepAngle = 45;
+			// Draw pie to screen.
+			t.Graphics.DrawPie(blackPen, x, y, width, height, startAngle, sweepAngle);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawPie(blackPen, new Rectangle( x, y, width, height), startAngle, sweepAngle);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawPolygonPoint() {
+			// Create pen.
+			Pen blackPen = new Pen(Color.Black, 3);
+			// Create points that define polygon.
+			Point point1 = new Point( 50,  50);
+			Point point2 = new Point(100,  25);
+			Point point3 = new Point(200,   5);
+			Point point4 = new Point(250,  50);
+			Point point5 = new Point(300, 100);
+			Point point6 = new Point(350, 200);
+			Point point7 = new Point(250, 250);
+			Point[] curvePoints = {
+				point1,
+				point2,
+				point3,
+				point4,
+				point5,
+				point6,
+				point7
+			};
+			// Draw polygon to screen.
+			t.Graphics.DrawPolygon(blackPen, curvePoints);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawPolygonPointF() {
+			// Create pen.
+			Pen blackPen = new Pen(Color.Black, 3);
+			// Create points that define polygon.
+			PointF point1 = new PointF( 50,  50);
+			PointF point2 = new PointF(100,  25);
+			PointF point3 = new PointF(200,   5);
+			PointF point4 = new PointF(250,  50);
+			PointF point5 = new PointF(300, 100);
+			PointF point6 = new PointF(350, 200);
+			PointF point7 = new PointF(250, 250);
+			PointF[] curvePoints = {
+									  point1,
+									  point2,
+									  point3,
+									  point4,
+									  point5,
+									  point6,
+									  point7
+								  };
+			// Draw polygon to screen.
+			t.Graphics.DrawPolygon(blackPen, curvePoints);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawRectangleFloat() {
+			// Create pen.
+			Pen blackPen = new Pen(Color.Black, 3);
+			// Create location and size of rectangle.
+			float x = 0.0F;
+			float y = 0.0F;
+			float width = 200.0F;
+			float height = 200.0F;
+			// Draw rectangle to screen.
+			t.Graphics.DrawRectangle(blackPen, x, y, width, height);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawRectangle(blackPen, (int)x, (int)y, (int)width, (int)height);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.DrawRectangle(blackPen, new Rectangle( (int)x, (int)y, (int)width, (int)height));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawRectanglesRectangleF() {
+			// Create pen.
+			Pen blackPen = new Pen(Color.Black, 3);
+			// Create array of rectangles.
+			RectangleF[] rects = {
+				new RectangleF(  0.0F,   0.0F, 100.0F, 200.0F),
+				new RectangleF(100.0F, 200.0F, 250.0F,  50.0F),
+				new RectangleF(300.0F,   0.0F,  50.0F, 100.0F)
+			};
+			// Draw rectangles to screen.
+			t.Graphics.DrawRectangles(blackPen, rects);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void DrawRectanglesRectangle() {
+			// Create pen.
+			Pen blackPen = new Pen(Color.Black, 3);
+			// Create array of rectangles.
+			Rectangle[] rects = {
+									 new Rectangle(  0,   0, 100, 200),
+									 new Rectangle(100, 200, 250,  50),
+									 new Rectangle(300,   0,  50, 100)
+								 };
+			// Draw rectangles to screen.
+			t.Graphics.DrawRectangles(blackPen, rects);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test] //TBD: add more combinations
+		public void DrawStringFloatFormat() {
+			// Create string to draw.
+			String drawString = "Sample Text";
+			// Create font and brush.
+			Font drawFont = new Font("Arial", 34, FontStyle.Italic);
+			SolidBrush drawBrush = new SolidBrush(Color.Black);
+			// Create point for upper-left corner of drawing.
+			float x = 150.0F;
+			float y =  50.0F;
+			// Set format of string.
+			StringFormat drawFormat = new StringFormat();
+			drawFormat.FormatFlags = StringFormatFlags.DirectionVertical;
+			// Draw string to screen.
+			t.Graphics.DrawString(drawString, drawFont, drawBrush, x, y, drawFormat);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			drawFormat.FormatFlags = StringFormatFlags.NoClip;
+			// Draw string to screen.
+			t.Graphics.DrawString(drawString, drawFont, drawBrush, x, y, drawFormat);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			drawFormat.FormatFlags = StringFormatFlags.FitBlackBox;
+			// Draw string to screen.
+			t.Graphics.DrawString(drawString, drawFont, drawBrush, x, y, drawFormat);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void EndContainerState() {
+			// Begin graphics container.
+			GraphicsContainer containerState = t.Graphics.BeginContainer();
+			// Translate world transformation.
+			t.Graphics.TranslateTransform(100.0F, 100.0F);
+			// Fill translated rectangle in container with red.
+			t.Graphics.FillRectangle(new SolidBrush(Color.Red), 0, 0, 200, 200);
+			t.Show();
+			// End graphics container.
+			t.Graphics.EndContainer(containerState);
+			// Fill untransformed rectangle with green.
+			t.Graphics.FillRectangle(new SolidBrush(Color.Green), 0, 0, 200, 200);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test] //TBD
+		public void EnumerateMetafile() {
+		}
+
+		[Test]
+		public void ExcludeClipRegion() {
+			// Create rectangle for exclusion.
+			Rectangle excludeRect = new Rectangle(100, 100, 200, 200);
+			// Set clipping region to exclude rectangle.
+			t.Graphics.ExcludeClip(excludeRect);
+			// Fill large rectangle to show clipping region.
+			t.Graphics.FillRectangle(new SolidBrush(Color.Blue), 0, 0, 300, 300);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void FillClosedCurvePointFillModeTension() {
+			// Create solid brush.
+			SolidBrush redBrush = new SolidBrush(Color.Red);
+			// Create array of points for curve.
+			Point point1 = new Point(100, 100);
+			Point point2 = new Point(200,  50);
+			Point point3 = new Point(250, 200);
+			Point point4 = new Point( 50, 150);
+			Point[] points = {point1, point2, point3, point4};
+			// Set fill mode.
+			FillMode newFillMode = FillMode.Winding;
+			// Set tension.
+			float tension = 0.68F;
+			// Fill curve on screen.
+			t.Graphics.FillClosedCurve(redBrush, points);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.FillClosedCurve(redBrush, points, newFillMode);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			newFillMode = FillMode.Alternate;
+			t.Graphics.FillClosedCurve(redBrush, points, newFillMode, tension);
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			t.Show();
+		}
+
+		[Test]
+		public void FillClosedCurvePointFFillModeTension() {
+			// Create solid brush.
+			SolidBrush redBrush = new SolidBrush(Color.Red);
+			// Create array of points for curve.
+			PointF point1 = new PointF(100.0F, 100.0F);
+			PointF point2 = new PointF(200.0F,  50.0F);
+			PointF point3 = new PointF(250.0F, 200.0F);
+			PointF point4 = new PointF( 50.0F, 150.0F);
+			PointF[] points = {point1, point2, point3, point4};
+			// Set fill mode.
+			FillMode newFillMode = FillMode.Winding;
+			// Set tension.
+			float tension = 0.68F;
+			// Fill curve on screen.
+			t.Graphics.FillClosedCurve(redBrush, points);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.FillClosedCurve(redBrush, points, newFillMode);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			newFillMode = FillMode.Alternate;
+			t.Graphics.FillClosedCurve(redBrush, points, newFillMode, tension);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void FillEllipse() {
+			// Create solid brush.
+			SolidBrush redBrush = new SolidBrush(Color.Red);
+			// Create location and size of ellipse.
+			int x = 0;
+			int y = 0;
+			int width = 200;
+			int height = 100;
+			// Fill ellipse on screen.
+			t.Graphics.FillEllipse(redBrush, x, y, width, height);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.FillEllipse(redBrush, new Rectangle( x, y, width, height));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void FillEllipseFloat() {
+			// Create solid brush.
+			SolidBrush redBrush = new SolidBrush(Color.Red);
+			// Create location and size of ellipse.
+			float x = 0.0F;
+			float y = 0.0F;
+			float width = 200.0F;
+			float height = 100.0F;
+			// Fill ellipse on screen.
+			t.Graphics.FillEllipse(redBrush, x, y, width, height);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.FillEllipse(redBrush, new RectangleF( x, y, width, height));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void FillPathEllipse() {
+			// Create solid brush.
+			SolidBrush redBrush = new SolidBrush(Color.Red);
+			// Create graphics path object and add ellipse.
+			GraphicsPath graphPath = new GraphicsPath();
+			graphPath.AddEllipse(0, 0, 200, 100);
+			// Fill graphics path to screen.
+			t.Graphics.FillPath(redBrush, graphPath);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void FillPieFloat() {
+			// Create solid brush.
+			SolidBrush redBrush = new SolidBrush(Color.Red);
+			// Create location and size of ellipse.
+			int x = 0;
+			int y = 0;
+			int width = 200;
+			int height = 100;
+			// Create start and sweep angles.
+			float startAngle =  0.0F;
+			float sweepAngle = 45.0F;
+			// Fill pie to screen.
+			t.Graphics.FillPie(redBrush, new Rectangle(x, y, width, height), startAngle, sweepAngle);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.FillPie(redBrush, x, y, width, height, (int)startAngle, (int)sweepAngle);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.FillPie(redBrush, (float)x, (float)y, (float)width, (float)height, startAngle, sweepAngle);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void FillPolygonPointFillMode() {
+			// Create solid brush.
+			SolidBrush blueBrush = new SolidBrush(Color.Blue);
+			// Create points that define polygon.
+			Point point1 = new Point( 50,  50);
+			Point point2 = new Point(100,  25);
+			Point point3 = new Point(200,   5);
+			Point point4 = new Point(250,  50);
+			Point point5 = new Point(300, 100);
+			Point point6 = new Point(350, 200);
+			Point point7 = new Point(250, 250);
+			Point[] curvePoints = {
+									   point1,
+									   point2,
+									   point3,
+									   point4,
+									   point5,
+									   point6,
+									   point7
+								   };
+
+			// Fill polygon to screen.
+			t.Graphics.FillPolygon(blueBrush, curvePoints, FillMode.Winding);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.FillPolygon(blueBrush, curvePoints, FillMode.Alternate);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.FillPolygon(blueBrush, curvePoints);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void FillPolygonPointFFillMode() {
+			// Create solid brush.
+			SolidBrush blueBrush = new SolidBrush(Color.Blue);
+			// Create points that define polygon.
+			PointF point1 = new PointF( 50.0F,  50.0F);
+			PointF point2 = new PointF(100.0F,  25.0F);
+			PointF point3 = new PointF(200.0F,   5.0F);
+			PointF point4 = new PointF(250.0F,  50.0F);
+			PointF point5 = new PointF(300.0F, 100.0F);
+			PointF point6 = new PointF(350.0F, 200.0F);
+			PointF point7 = new PointF(250.0F, 250.0F);
+			PointF[] curvePoints = {
+				point1,
+				point2,
+				point3,
+				point4,
+				point5,
+				point6,
+				point7
+			};
+
+			// Fill polygon to screen.
+			t.Graphics.FillPolygon(blueBrush, curvePoints, FillMode.Winding);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.FillPolygon(blueBrush, curvePoints, FillMode.Alternate);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.FillPolygon(blueBrush, curvePoints);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void FillRectangle() {
+			// Create solid brush.
+			SolidBrush blueBrush = new SolidBrush(Color.Blue);
+			// Create location and size of rectangle.
+			int x = 0;
+			int y = 0;
+			int width = 300;
+			int height = 200;
+			// Fill rectangle to screen.
+			t.Graphics.FillRectangle(blueBrush, x, y, width, height);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.FillRectangle(blueBrush, new Rectangle( x, y, width, height));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void FillRectangleFloat() {
+			// Create solid brush.
+			SolidBrush blueBrush = new SolidBrush(Color.Blue);
+			// Create location and size of rectangle.
+			float x = 0.0F;
+			float y = 0.0F;
+			float width = 300.0F;
+			float height = 200.0F;
+			// Fill rectangle to screen.
+			t.Graphics.FillRectangle(blueBrush, x, y, width, height);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+			SetUp();
+
+			t.Graphics.FillRectangle(blueBrush, new RectangleF( x, y, width, height));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void FillRectanglesRectangle() {
+			// Create solid brush.
+			SolidBrush blueBrush = new SolidBrush(Color.Blue);
+			// Create array of rectangles.
+			Rectangle[] rects = {
+				new Rectangle(  0,   0, 100, 200),
+				new Rectangle(100, 200, 250,  50),
+				new Rectangle(300,   0,  50, 100)
+			};
+			// Fill rectangles to screen.
+			t.Graphics.FillRectangles(blueBrush, rects);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void FillRectanglesRectangleF() {
+			// Create solid brush.
+			SolidBrush blueBrush = new SolidBrush(Color.Blue);
+			// Create array of rectangles.
+			RectangleF[] rects = {
+									 new RectangleF(  0.0F,   0.0F, 100.0F, 200.0F),
+									 new RectangleF(100.0F, 200.0F, 250.0F,  50.0F),
+									 new RectangleF(300.0F,   0.0F,  50.0F, 100.0F)
+								 };
+			// Fill rectangles to screen.
+			t.Graphics.FillRectangles(blueBrush, rects);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void FillRegionRectangle() {
+			// Create solid brush.
+			SolidBrush blueBrush = new SolidBrush(Color.Blue);
+			// Create rectangle for region.
+			Rectangle fillRect = new Rectangle(100, 150, 200, 250);
+			// Create region for fill.
+			Region fillRegion = new Region(fillRect);
+			// Fill region to screen.
+			t.Graphics.FillRegion(blueBrush, fillRegion);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void FlushTest() {
+			t.Graphics.Flush();
+			t.Graphics.Flush(FlushIntention.Flush);
+		}
+
+		[Test]
+		public void IntersectClipRegion() {
+			// Set clipping region.
+			Rectangle clipRect = new Rectangle(0, 0, 200, 300);
+			Region clipRegion = new Region(clipRect);
+			t.Graphics.SetClip(clipRegion, CombineMode.Replace);
+			// Update clipping region to intersection of
+			//  existing region with specified rectangle.
+			Rectangle intersectRect = new Rectangle(100, 100, 200, 300);
+			Region intersectRegion = new Region(intersectRect);
+			t.Graphics.IntersectClip(intersectRegion);
+			// Fill rectangle to demonstrate effective clipping region.
+			t.Graphics.FillRectangle(new SolidBrush(Color.Blue), 0, 0, 500, 600);
+			t.Show();
+			// Reset clipping region to infinite.
+			t.Graphics.ResetClip();
+			// Draw clipRect and intersectRect to screen.
+			t.Graphics.DrawRectangle(new Pen(Color.Black), clipRect);
+			t.Show();
+			t.Graphics.DrawRectangle(new Pen(Color.Red), intersectRect);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void IsVisible4Float() {
+			// Set clip region.
+			Region clipRegion = new Region(new Rectangle(50, 50, 100, 100));
+			t.Graphics.SetClip(clipRegion, CombineMode.Replace);
+			// Set up coordinates of rectangles.
+			float x1 =  100.0F;
+			float y1 =  100.0F;
+			float width1 = 20.0F;
+			float height1 = 20.0F;
+			float x2 = 200.0F;
+			float y2 = 200.0F;
+			float width2 = 20.0F;
+			float height2 = 20.0F;
+			// If rectangle is visible, fill it.
+			if (t.Graphics.IsVisible(x1, y1, width1, height1)) {
+				t.Graphics.FillRectangle(new SolidBrush(Color.Red), x1, y1, width1, height1);
+				t.Show();
+			}
+			if (t.Graphics.IsVisible(x2, y2, width2, height2)) {
+				t.Graphics.FillRectangle(new SolidBrush(Color.Blue), x2, y2, width2, height2);
+				t.Show();
+			}
+
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void MeasureCharacterRangesRegions() {
+			// Set up string.
+			string measureString = "First and Second ranges";
+			Font stringFont = new Font("Times New Roman", 16.0F);
+			// Set character ranges to "First" and "Second".
+			CharacterRange[] characterRanges = {
+				new CharacterRange(0, 5),
+				new CharacterRange(10, 6)
+			};
+			// Create rectangle for layout.
+			float x = 50.0F;
+			float y = 50.0F;
+			float width = 35.0F;
+			float height = 200.0F;
+			RectangleF layoutRect = new RectangleF(x, y, width, height);
+			// Set string format.
+			StringFormat stringFormat = new StringFormat();
+			stringFormat.FormatFlags = StringFormatFlags.DirectionVertical;
+			stringFormat.SetMeasurableCharacterRanges(characterRanges);
+			// Draw string to screen.
+			t.Graphics.DrawString(
+				measureString,
+				stringFont,
+				Brushes.Black,
+				x, y,
+				stringFormat);
+			// Measure two ranges in string.
+			Region[] stringRegions = new Region[2];
+			stringRegions = t.Graphics.MeasureCharacterRanges(
+				measureString,
+				stringFont,
+				layoutRect,
+				stringFormat);
+			// Draw rectangle for first measured range.
+			RectangleF measureRect1 = stringRegions[0].GetBounds(t.Graphics);
+			t.Graphics.DrawRectangle(
+				new Pen(Color.Red, 1),
+				Rectangle.Round(measureRect1));
+			t.Show();
+			// Draw rectangle for second measured range.
+			RectangleF measureRect2 = stringRegions[1].GetBounds(t.Graphics);
+			t.Graphics.DrawRectangle(
+				new Pen(Color.Blue, 1),
+				Rectangle.Round(measureRect2));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test] //TBD: add more overloads
+		public void MeasureStringSizeFFormatInts() {
+			// Set up string.
+			string measureString = "Measure String";
+			Font stringFont = new Font("Arial", 16);
+			// Set maximum layout size.
+			SizeF layoutSize = new SizeF(100.0F, 200.0F);
+			// Set string format.
+			StringFormat newStringFormat = new StringFormat();
+			newStringFormat.FormatFlags = StringFormatFlags.DirectionVertical;
+			// Measure string.
+			int charactersFitted;
+			int linesFilled;
+			SizeF stringSize = new SizeF();
+			stringSize = t.Graphics.MeasureString(
+				measureString,
+				stringFont,
+				layoutSize,
+				newStringFormat,
+				out charactersFitted,
+				out linesFilled);
+			// Draw rectangle representing size of string.
+			t.Graphics.DrawRectangle(
+				new Pen(Color.Red, 1),
+				0.0F, 0.0F, stringSize.Width, stringSize.Height);
+			t.Show();
+			// Draw string to screen.
+			t.Graphics.DrawString(
+				measureString,
+				stringFont,
+				Brushes.Black,
+				new PointF(0, 0),
+				newStringFormat);
+			t.Show();
+			// Draw output parameters to screen.
+			string outString = "chars " + charactersFitted + ", lines " + linesFilled;
+			t.Graphics.DrawString(
+				outString,
+				stringFont,
+				Brushes.Black,
+				new PointF(100, 0));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void MultiplyTransform() {
+			// Create transform matrix.
+			Matrix transformMatrix = new Matrix();
+			// Translate matrix, prepending translation vector.
+			transformMatrix.Translate(200.0F, 100.0F);
+			// Rotate transformation matrix of graphics object,
+			//  prepending rotation matrix.
+			t.Graphics.RotateTransform(30.0F);
+			// Multiply (append to) transformation matrix of
+			//  graphics object to translate graphics transformation.
+			t.Graphics.MultiplyTransform(transformMatrix);
+			// Draw rotated, translated ellipse.
+			t.Graphics.DrawEllipse(new Pen(Color.Blue, 3), -80, -40, 160, 80);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void MultiplyTransformMatrixOrder() {
+			// Create transform matrix.
+			Matrix transformMatrix = new Matrix();
+			// Translate matrix, prepending translation vector.
+			transformMatrix.Translate(200.0F, 100.0F);
+			// Rotate transformation matrix of graphics object,
+			//  prepending rotation matrix.
+			t.Graphics.RotateTransform(30.0F);
+			// Multiply (append to) transformation matrix of
+			//  graphics object to translate graphics transformation.
+			t.Graphics.MultiplyTransform(transformMatrix, MatrixOrder.Append);
+			// Draw rotated, translated ellipse.
+			t.Graphics.DrawEllipse(new Pen(Color.Blue, 3), -80, -40, 160, 80);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void MultiplyTransformMatrixOrder1() {
+			// Create transform matrix.
+			Matrix transformMatrix = new Matrix();
+			// Translate matrix, prepending translation vector.
+			transformMatrix.Translate(200.0F, 100.0F);
+			// Rotate transformation matrix of graphics object,
+			//  prepending rotation matrix.
+			t.Graphics.RotateTransform(30.0F);
+			// Multiply (append to) transformation matrix of
+			//  graphics object to translate graphics transformation.
+			t.Graphics.MultiplyTransform(transformMatrix, MatrixOrder.Prepend);
+			// Draw rotated, translated ellipse.
+			t.Graphics.DrawEllipse(new Pen(Color.Blue, 3), -80, -40, 160, 80);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void ResetClipIntersectClipRectangleF() {
+			// Set clipping region.
+			Rectangle clipRect = new Rectangle(0, 0, 200, 200);
+			t.Graphics.SetClip(clipRect);
+			// Update clipping region to intersection of existing region with new rectangle.
+			RectangleF intersectRectF = new RectangleF(100.0F, 100.0F, 200.0F, 200.0F);
+			t.Graphics.IntersectClip(intersectRectF);
+			// Fill rectangle to demonstrate effective clipping region.
+			t.Graphics.FillRectangle(new SolidBrush(Color.Blue), 0, 0, 500, 500);
+			// Reset clipping region to infinite.
+			t.Graphics.ResetClip();
+			// Draw clipRect and intersectRect to screen.
+			t.Graphics.DrawRectangle(new Pen(Color.Black), clipRect);
+			t.Graphics.DrawRectangle(new Pen(Color.Red), Rectangle.Round(intersectRectF));
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void SaveRestoreTranslate() {
+			// Translate transformation matrix.
+			t.Graphics.TranslateTransform(100, 0);
+			// Save translated graphics state.
+			GraphicsState transState = t.Graphics.Save();
+			// Reset transformation matrix to identity and fill rectangle.
+			t.Graphics.ResetTransform();
+			t.Graphics.FillRectangle(new SolidBrush(Color.Red), 0, 0, 100, 100);
+			t.Show();
+			// Restore graphics state to translated state and fill second rectangle.
+			t.Graphics.Restore(transState);
+			t.Graphics.FillRectangle(new SolidBrush(Color.Blue), 0, 0, 100, 100);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void RotateTransformAngleMatrixOrder() {
+			// Set world transform of graphics object to translate.
+			t.Graphics.TranslateTransform(100.0F, 0.0F);
+			// Then to rotate, appending rotation matrix.
+			t.Graphics.RotateTransform(30.0F, MatrixOrder.Append);
+			// Draw translated, rotated ellipse to screen.
+			t.Graphics.DrawEllipse(new Pen(Color.Blue, 3), 0, 0, 200, 80);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void RotateTransformAngleMatrixOrder1() {
+			// Set world transform of graphics object to translate.
+			t.Graphics.TranslateTransform(100.0F, 0.0F);
+			// Then to rotate, appending rotation matrix.
+			t.Graphics.RotateTransform(30.0F, MatrixOrder.Prepend);
+			// Draw translated, rotated ellipse to screen.
+			t.Graphics.DrawEllipse(new Pen(Color.Blue, 3), 0, 0, 200, 80);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void ScaleTransformFloatMatrixOrder() {
+			// Set world transform of graphics object to rotate.
+			t.Graphics.RotateTransform(30.0F);
+			// Then to scale, appending to world transform.
+			t.Graphics.ScaleTransform(3.0F, 1.0F, MatrixOrder.Append);
+			// Draw rotated, scaled rectangle to screen.
+			t.Graphics.DrawRectangle(new Pen(Color.Blue, 3), 50, 0, 100, 40);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void ScaleTransformFloatMatrixOrder1() {
+			// Set world transform of graphics object to rotate.
+			t.Graphics.RotateTransform(30.0F);
+			// Then to scale, appending to world transform.
+			t.Graphics.ScaleTransform(3.0F, 1.0F, MatrixOrder.Prepend);
+			// Draw rotated, scaled rectangle to screen.
+			t.Graphics.DrawRectangle(new Pen(Color.Blue, 3), 50, 0, 100, 40);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test] //TBD: add more combination
+		public void SetClipRegionCombine() {
+			// Create region for clipping.
+			Region clipRegion = new Region(new Rectangle(0, 0, 200, 100));
+			// Set clipping region of graphics to region.
+			t.Graphics.SetClip(clipRegion, CombineMode.Replace);
+			// Fill rectangle to demonstrate clip region.
+			t.Graphics.FillRectangle(new SolidBrush(Color.Black), 0, 0, 500, 300);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void TransformPointsPointF() {
+			// Create array of two points.
+			PointF[] points = {new PointF(0.0F, 0.0F),
+								  new PointF(100.0F, 50.0F)};
+			// Draw line connecting two untransformed points.
+			t.Graphics.DrawLine(new Pen(Color.Blue, 3),
+				points[0],
+				points[1]);
+			// Set world transformation of Graphics object to translate.
+			t.Graphics.TranslateTransform(40.0F, 30.0F);
+			// Transform points in array from world to page coordinates.
+			t.Graphics.TransformPoints(CoordinateSpace.Page,
+				CoordinateSpace.World,
+				points);
+			// Reset world transformation.
+			t.Graphics.ResetTransform();
+			// Draw line that connects transformed points.
+			t.Graphics.DrawLine(new Pen(Color.Red, 3),
+				points[0],
+				points[1]);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void TranslateClipFloat() {
+			// Create rectangle for clipping region.
+			RectangleF clipRect = new RectangleF(0.0F, 0.0F, 100.0F, 100.0F);
+			// Set clipping region of graphics to rectangle.
+			t.Graphics.SetClip(clipRect);
+			// Translate clipping region.
+			float dx = 50.0F;
+			float dy = 50.0F;
+			t.Graphics.TranslateClip(dx, dy);
+			// Fill rectangle to demonstrate translated clip region.
+			t.Graphics.FillRectangle(new SolidBrush(Color.Black), 0, 0, 500, 300);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void TranslateTransformAngleMatrixOrder() {
+			// Set world transform of graphics object to rotate.
+			t.Graphics.RotateTransform(30.0F);
+			// Then to translate, appending to world transform.
+			t.Graphics.TranslateTransform(100.0F, 0.0F, MatrixOrder.Append);
+			// Draw rotated, translated ellipse to screen.
+			t.Graphics.DrawEllipse(new Pen(Color.Blue, 3), 0, 0, 200, 80);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+
+		[Test]
+		public void TranslateTransformAngleMatrixOrder1() {
+			// Set world transform of graphics object to rotate.
+			t.Graphics.RotateTransform(30.0F);
+			// Then to translate, appending to world transform.
+			t.Graphics.TranslateTransform(100.0F, 0.0F, MatrixOrder.Prepend);
+			// Draw rotated, translated ellipse to screen.
+			t.Graphics.DrawEllipse(new Pen(Color.Blue, 3), 0, 0, 200, 80);
+			t.Show();
+			Assert.IsTrue(t.Compare(TOLERANCE));
+		}
+	}
+
+
+	#endregion
+
+	#region GraphicsFixturePropClip
+
+	[TestFixture]
+	public class GraphicsFixturePropClip : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.Clip = new Region(new Rectangle(10, 10, 100, 100));
+		}
+	}
+
+	#endregion
+
+	#region GraphicsFixturePropCompositingMode
+
+	[TestFixture]
+	public class GraphicsFixturePropCompositingMode1 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.CompositingMode = CompositingMode.SourceCopy;
+		}
+	}
+
+	[TestFixture]
+	public class GraphicsFixturePropCompositingMode2 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.CompositingMode = CompositingMode.SourceOver;
+		}
+	}
+
+	#endregion
+
+	#region GraphicsFixturePropInterpolationMode
+
+	[TestFixture]
+	public class GraphicsFixturePropInterpolationMode1 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.InterpolationMode = InterpolationMode.Bilinear;
+		}
+	}
+
+	[TestFixture]
+	public class GraphicsFixturePropInterpolationMode2 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.InterpolationMode = InterpolationMode.Bicubic;
+		}
+	}
+
+	#endregion
+
+	#region GraphicsFixturePropPageScale
+
+	[TestFixture]
+	public class GraphicsFixturePropPageScale : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.PageScale = 4.34f;
+		}
+	}
+
+	#endregion
+
+	#region GraphicsFixturePropPageUnit
+
+	[TestFixture]
+	public class GraphicsFixturePropPageUnit1 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.PageUnit = GraphicsUnit.Display;
+		}
+	}
+
+	[TestFixture]
+	public class GraphicsFixturePropPageUnit2 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.PageUnit = GraphicsUnit.Document;
+		}
+	}
+
+	[TestFixture]
+	public class GraphicsFixturePropPageUnit3 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.PageUnit = GraphicsUnit.Inch;
+		}
+	}
+
+	[TestFixture]
+	public class GraphicsFixturePropPageUnit4 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.PageUnit = GraphicsUnit.Millimeter;
+		}
+	}
+
+	[TestFixture]
+	public class GraphicsFixturePropPageUnit5 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.PageUnit = GraphicsUnit.Pixel;
+		}
+	}
+
+	[TestFixture]
+	public class GraphicsFixturePropPageUnit6 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.PageUnit = GraphicsUnit.Point;
+		}
+	}
+
+//	[TestFixture]
+//	public class GraphicsFixturePropPageUnit7 : GraphicsFixture {
+//		public override void SetUp() {
+//			base.SetUp ();
+//
+//			t.Graphics.PageUnit = GraphicsUnit.World;
+//		}
+//	}
+
+	#endregion
+
+	#region GraphicsFixturePropPixelOffsetMode
+
+	[TestFixture]
+	public class GraphicsFixturePropPixelOffsetMode : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.PixelOffsetMode = PixelOffsetMode.Half;
+		}
+	}
+
+	[TestFixture]
+	public class GraphicsFixturePropPixelOffsetMode1 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
+		}
+	}
+
+	[TestFixture]
+	public class GraphicsFixturePropPixelOffsetMode2 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+		}
+	}
+
+	#endregion
+
+	#region GraphicsFixturePropRenderingOrigin
+
+	[TestFixture]
+	public class GraphicsFixturePropRenderingOrigin : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.RenderingOrigin = new Point(12, 23);
+		}
+	}
+
+	#endregion
+
+	/// <summary>
+	/// TBD: add more variants
+	/// </summary>
+	#region GraphicsFixturePropSmoothingMode 
+
+	[TestFixture]
+	public class GraphicsFixturePropSmoothingMode : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
+		}
+	}
+
+	[TestFixture]
+	public class GraphicsFixturePropSmoothingMode1 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.SmoothingMode = SmoothingMode.HighSpeed;
+		}
+	}
+
+	#endregion
+
+	#region GraphicsFixturePropTextContrast
+
+	[TestFixture]
+	public class GraphicsFixturePropTextContrast : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.TextContrast = 9;
+		}
+	}
+
+	#endregion
+
+	#region GraphicsFixturePropTextRenderingHint
+
+	[TestFixture]
+	public class GraphicsFixturePropTextRenderingHint : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
+		}
+	}
+
+	[TestFixture]
+	public class GraphicsFixturePropTextRenderingHint1 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
+		}
+	}
+
+	[TestFixture]
+	public class GraphicsFixturePropTextRenderingHint2 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
+		}
+	}
+
+	[TestFixture]
+	public class GraphicsFixturePropTextRenderingHint3 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixel;
+		}
+	}
+
+	[TestFixture]
+	public class GraphicsFixturePropTextRenderingHint4 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
+		}
+	}
+
+	[TestFixture]
+	public class GraphicsFixturePropTextRenderingHint5 : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.TextRenderingHint = TextRenderingHint.SystemDefault;
+		}
+	}
+
+	#endregion
+
+	#region GraphicsFixturePropTransform
+
+	[TestFixture]
+	public class GraphicsFixturePropTransform : GraphicsFixture {
+		public override void SetUp() {
+			base.SetUp ();
+
+			t.Graphics.Transform = new Matrix(0, 1, 2, 0, 0, 0);
+		}
+	}
+
+	#endregion
+
+}

+ 202 - 0
mcs/class/System.Drawing/Test/DrawingTest/Test/Image.cs

@@ -0,0 +1,202 @@
+using System;
+using NUnit.Framework;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using DrawingTestHelper;
+using System.IO;
+
+namespace Test.Sys.Drawing {
+	[TestFixture]
+	public class ImageFixture {
+		DrawingTest t;
+		[SetUp]
+		public void SetUp () {
+			t = DrawingTest.Create (256, 256);
+			Image im=new Bitmap (@"C:\views\andrews_main\studio\GH\DevQA\utils\drawings\SystemDrawingTests\Test\Bitmap1.png"); 
+			t.Graphics.DrawImageUnscaled (im, 0, 0);
+		}
+		[Test]
+		public void Clone () {
+			Image im1 = (Image) t.Bitmap.Clone ();
+			Assert.IsFalse (Object.ReferenceEquals (im1, t.Bitmap));
+			Assert.AreEqual (DrawingTest.CalculateNorm ((Bitmap)im1),
+				DrawingTest.CalculateNorm (t.Bitmap));
+			t.Graphics.FillRectangle (Brushes.Beige, 0, 0, 100, 100);
+			Assert.IsFalse (DrawingTest.CalculateNorm ((Bitmap)im1) ==
+				DrawingTest.CalculateNorm (t.Bitmap));
+		}
+		[Test]
+		public void GetHashCodeTest () {
+			Assert.IsFalse (t.Bitmap.GetHashCode () == 0);
+			Bitmap im1 = new Bitmap (10, 20);
+			Assert.IsFalse (t.Bitmap.GetHashCode () == im1.GetHashCode ());
+		}
+		[Test]
+		public void GetBounds () {
+			GraphicsUnit unit = new GraphicsUnit();
+			Assert.AreEqual (new RectangleF (0, 0, 256, 256),
+				t.Bitmap.GetBounds (ref unit));
+			Assert.AreEqual (GraphicsUnit.Pixel, unit);
+		}
+		[Test]
+		[Category ("NotWorking")]
+		public void GetEncoderParameterList () {
+			Assert.Fail ("Test not implemented - undocumented parameter");
+		}
+		[Test]
+		public void GetFrameCount () {
+			Assert.AreEqual (1, t.Bitmap.GetFrameCount (FrameDimension.Page));
+			Assert.AreEqual (1, t.Bitmap.GetFrameCount (FrameDimension.Time));
+			Assert.AreEqual (1, t.Bitmap.GetFrameCount (new FrameDimension (Guid.NewGuid ())));
+		}
+		[Test]
+		[Category ("NotWorking")]
+		public void GetPropertyItem () {
+			Assert.Fail ("Test not implemented - undocumented parameter");
+		}
+		[Test]
+		[Category ("NotWorking")]
+		public void RemovePropertyItem () {
+			Assert.Fail ("Test not implemented - undocumented parameter");
+		}
+		static bool ThumbnailCallback() {
+			return false;
+		}
+		[Test]
+		public void GetThumbnailImage() {
+			t.Show ();
+			Image.GetThumbnailImageAbort myCallback =
+				new Image.GetThumbnailImageAbort(ThumbnailCallback);
+			Image myThumbnail = t.Bitmap.GetThumbnailImage(
+				10, 10, myCallback, IntPtr.Zero);
+			t.Graphics.DrawImageUnscaled (myThumbnail, 100, 75);
+			t.Show ();
+		}
+		[Test]
+		public void RotateFlip () {
+			t.Show ();
+			t.Bitmap.RotateFlip (RotateFlipType.Rotate90FlipY);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+		}
+		[Test]
+		public void Save_string () {
+			t.Bitmap.Save ("test.png");
+			using (FileStream r = new FileStream ("test.png", FileMode.Open)) {
+				Bitmap b1 = new Bitmap (r);
+				Assert.AreEqual (DrawingTest.CalculateNorm (t.Bitmap),
+					DrawingTest.CalculateNorm (b1));
+			}
+			File.Delete ("test.png");
+		}
+		[Test]
+		public void Save_Stream_ImageFormat () {
+			using (FileStream w = new FileStream ("test.png", FileMode.OpenOrCreate)) {
+				t.Bitmap.Save (w, ImageFormat.Png);
+			}
+			using (FileStream r = new FileStream ("test.png", FileMode.Open)) {
+				Bitmap b1 = new Bitmap (r);
+				Assert.AreEqual (DrawingTest.CalculateNorm (t.Bitmap),
+					DrawingTest.CalculateNorm (b1));
+			}
+			File.Delete ("test.png");
+		}
+		[Test]
+		public void Save_string_ImageFormat () {
+			t.Bitmap.Save ("test.png", ImageFormat.Png);
+			using (FileStream r = new FileStream ("test.png", FileMode.Open)) {
+				Bitmap b1 = new Bitmap (r);
+				Assert.AreEqual (DrawingTest.CalculateNorm (t.Bitmap),
+					DrawingTest.CalculateNorm (b1));
+			}
+			File.Delete ("test.png");
+		}
+		[Test]
+		[Category("NotWorking")]
+		public void Save_Stream_ImageCodecInfo_EncoderParameters () {
+			using (FileStream w = new FileStream ("test.png", FileMode.OpenOrCreate)) {
+				foreach (ImageCodecInfo i in ImageCodecInfo.GetImageEncoders()) {
+					if (i.FilenameExtension.IndexOf ("png") != -1) {
+						t.Bitmap.Save (w, i, new EncoderParameters ());
+						break;
+					}
+				}
+			}
+			using (FileStream r = new FileStream ("test.png", FileMode.Open)) {
+				Bitmap b1 = new Bitmap (r);
+				Assert.AreEqual (DrawingTest.CalculateNorm (t.Bitmap),
+					DrawingTest.CalculateNorm (b1));
+			}
+			File.Delete ("test.png");
+		}
+		[Test]
+		[Category("NotWorking")]
+		public void Save_string_ImageCodecInfo_EncoderParameters () {
+			foreach (ImageCodecInfo i in ImageCodecInfo.GetImageEncoders()) {
+				if (i.FilenameExtension.IndexOf ("png") != -1) {
+					t.Bitmap.Save ("test.png", i, new EncoderParameters ());
+					break;
+				}
+			}
+			using (FileStream r = new FileStream ("test.png", FileMode.Open)) {
+				Bitmap b1 = new Bitmap (r);
+				Assert.AreEqual (DrawingTest.CalculateNorm (t.Bitmap),
+					DrawingTest.CalculateNorm (b1));
+			}
+			File.Delete ("test.png");
+		}
+		[Test]
+		[Category ("NotWorking")]
+		public void SaveAdd () {
+			Assert.Fail ("Test not implemented");
+		}
+		[Test]
+		[Category ("NotWorking")]
+		public void SelectActiveFrame () {
+			Assert.Fail ("Test not implemented");
+		}
+		[Test]
+		[Category ("NotWorking")]
+		public void SetPropertyItem () {
+			Assert.Fail ("Test not implemented - undocumented parameter");
+		}
+		[Test]
+		public new void ToString () {
+			Assert.AreEqual ("System.Drawing.Bitmap", t.Bitmap.ToString ());
+		}
+		[Test]
+		public void Height () {
+			Assert.AreEqual (256, t.Bitmap.Height);
+		}
+		[Test]
+		public void Width () {
+			Assert.AreEqual (256, t.Bitmap.Width);
+		}
+		[Test]
+		public void HorizontalResolution () {
+			Assert.AreEqual (96, t.Bitmap.HorizontalResolution);
+		}
+		[Test]
+		public void VerticalResolution () {
+			Assert.AreEqual (96, t.Bitmap.VerticalResolution);
+		}
+		[Test]
+		public void PixelFormatTest () {
+			Assert.AreEqual (PixelFormat.Format32bppArgb, t.Bitmap.PixelFormat);
+		}
+		[Test]
+		public void PropertyIdList () {
+			Assert.AreEqual (new int [0], t.Bitmap.PropertyIdList);
+		}
+		[Test]
+		public void PropertyItems () {
+			Assert.AreEqual (new PropertyItem [0], t.Bitmap.PropertyItems);
+		}
+		[Test]
+		public void FrameDimensionsList () {
+			Assert.AreEqual (new Guid [] {FrameDimension.Page.Guid},
+				t.Bitmap.FrameDimensionsList);
+		}
+	}
+}

+ 17 - 0
mcs/class/System.Drawing/Test/DrawingTest/Test/Makefile

@@ -0,0 +1,17 @@
+MCS=mcs
+NUNIT_FLAGS=/exclude=NotWorking
+
+sources=AssemblyInfo.cs Bitmap.cs Brush.cs Graphics.cs Image.cs Pen.cs Region.cs
+
+DRAWING_TEST_HELPER=DrawingTestHelper.dll
+EXOCORTEX=Exocortex.DSP.dll
+
+Test.dll: $(sources) $(DRAWING_TEST_HELPER)
+	$(MCS) -t:library $(sources) -r:$(DRAWING_TEST_HELPER) -r:$(EXOCORTEX) -r:nunit.framework -r:System.Drawing -out:Test.dll
+
+$(DRAWING_TEST_HELPER):
+	cd ../DrawingTestHelper && make
+	cp ../DrawingTestHelper/*.dll .
+
+run-test: Test.dll
+	MONO_PATH="../../../../../class/lib/default::$(MONO_PATH)" /home/andrews/monobuild/mono/runtime/mono-wrapper --debug ../../../../../class/lib/default/nunit-console.exe Test.dll $(NUNIT_FLAGS)

+ 267 - 0
mcs/class/System.Drawing/Test/DrawingTest/Test/Pen.cs

@@ -0,0 +1,267 @@
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using NUnit.Framework;
+using DrawingTestHelper;
+
+namespace Test.Sys.Drawing
+{
+	/// <summary>
+	/// Summary description for Pen.
+	/// </summary>
+	[TestFixture]
+	public class PenFixture {
+		//TODO: Brush, CompoundArray, CustomEndCap, CustomStartCap,
+		//StartCap, EndCap, PenType, Transform
+		DrawingTest t;
+		Pen p;
+		[SetUp]
+		public void SetUp () {
+			t = DrawingTest.Create (256, 256);
+			p = new Pen (Color.Blue);
+			p.Width = 10;
+		}
+		[Test]
+		public void InitAlignment () {
+			Pen p = new Pen (Color.Blue);
+			Assert.AreEqual (PenAlignment.Center, p.Alignment);
+		}
+		[Test]
+		[Category ("test1")]
+		public void Width () {
+			Assert.AreEqual (10, p.Width);
+			t.Graphics.DrawLine (p, 0, 0, 64, 64);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+			p.Width = 0;
+			t.Graphics.DrawLine (p, 32, 0, 35, 64);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+			p.Width = 10;
+			t.Graphics.DrawLine (p, 0, 64, 64, 70);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+		}
+		[Test]
+		public void DashStyleTest () {
+			Assert.AreEqual (DashStyle.Solid, p.DashStyle);
+			t.Graphics.DrawLine (p, 0, 30, 256, 30);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+			
+			p.DashStyle = DashStyle.Dash;
+			p.Width = 10;
+			t.Graphics.DrawLine (p, 0, 600, 200, 60);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+			
+			p.DashStyle = DashStyle.DashDot;
+			t.Graphics.FillRectangle (Brushes.Black, 0, 0, 256, 256);
+			t.Graphics.DrawLine (p, 0, 0, 200, 200);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+			
+			p.DashStyle = DashStyle.DashDotDot;
+			t.Graphics.FillRectangle (Brushes.Black, 0, 0, 256, 256);
+			t.Graphics.DrawLine (p, 0, 0, 200, 200);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			p.DashStyle = DashStyle.Dot;
+			t.Graphics.FillRectangle (Brushes.Black, 0, 0, 256, 256);
+			t.Graphics.DrawLine (p, 0, 0, 200, 200);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			p.DashStyle = DashStyle.Custom;
+			t.Graphics.FillRectangle (Brushes.Black, 0, 0, 256, 256);
+			t.Graphics.DrawLine (p, 0, 0, 200, 200);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+		}
+		//The following tests DashOffset and DashPattern
+		[Test]
+		public void DashCustomStyle () {
+			p.DashStyle = DashStyle.Custom;
+			p.Width = 10;
+			Assert.AreEqual (new float [] {1F}, p.DashPattern);
+			Assert.AreEqual (0F, p.DashOffset);
+
+			p.DashPattern = new float [] {2, 3, 1.15F, 0.05F};
+			t.Graphics.FillRectangle (Brushes.Black, 0, 0, 256, 256);
+			t.Graphics.DrawLine (p, 0, 0, 200, 10);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+			p.DashOffset = 10F;
+			t.Graphics.DrawLine (p, 0, 50, 200, 50);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+			p.DashPattern = new float [] {2, 3, 1.15F, 0.05F, 1.74321F};
+			p.DashOffset = 10.2F;
+			t.Graphics.DrawLine (p, 0, 100, 200, 90);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+			p.DashPattern = new float [] {2, 3, 1.15F, 0.05F, 1.74321F};
+			p.DashOffset = 10.2F;
+			t.Graphics.DrawLine (p, 0, 100, 200, 90);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+		}
+		[Test]
+		public void DashCapTest () {
+			Assert.AreEqual (DashCap.Flat, p.DashCap);
+			p.DashStyle = DashStyle.DashDot;
+			t.Graphics.DrawLine (p, 0, 0, 200, 10);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			p.DashCap = DashCap.Round;
+			t.Graphics.DrawLine (p, 0, 50, 200, 61.7F);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			p.DashCap = DashCap.Triangle;
+			t.Graphics.DrawLine (p, 0F, 92.3F, 200F, 117.9F);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+		}
+		[Test]
+		public void LineJoinTest () {
+			Assert.AreEqual (LineJoin.Miter, p.LineJoin);
+			Point [] points = new Point [] {
+											   new Point(40, 10), new Point (200, 11),
+											   new Point (100, 40)};
+			t.Graphics.DrawPolygon (p, points);
+			t.Graphics.DrawPolygon (Pens.White, points);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			p.LineJoin = LineJoin.Bevel;
+			points =new Point [] {
+									 new Point(40, 70), new Point (200, 79),
+									 new Point (100, 100)};
+			t.Graphics.DrawPolygon (p, points);
+			t.Graphics.DrawPolygon (Pens.White, points);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			p.LineJoin = LineJoin.MiterClipped;
+			points = new Point [] {
+									  new Point(40, 120), new Point (200, 117),
+									  new Point (80, 135)};
+			t.Graphics.DrawPolygon (p, points);
+			t.Graphics.DrawPolygon (Pens.White, points);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			p.LineJoin = LineJoin.Round;
+			points = new Point [] {
+									  new Point(40, 170), new Point (200, 175),
+									  new Point (100, 210)};
+			t.Graphics.DrawPolygon (p, points);
+			t.Graphics.DrawPolygon (Pens.White, points);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+		}
+		[Test]
+		public void PenAlignmentTest () {
+			Point [] points = new Point [] {
+				new Point (20, 20), new Point (40, 40), new Point (60, 20),
+				new Point (60, 60), new Point (20, 60)};
+			GraphicsPath path = new GraphicsPath ();
+			path.AddPolygon (points);
+			Matrix mx = new Matrix (1, 0, 0, 1, 90, 0);
+			Matrix mrx = new Matrix (1, 0, 0, 1, -180, 0);
+			Matrix my = new Matrix (1, 0, 0, 1, 0, 100);
+						
+			Assert.AreEqual (PenAlignment.Center, p.Alignment);
+			t.Graphics.DrawPath (p, path);
+			t.Graphics.DrawPath (Pens.White, path);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			p.Alignment = PenAlignment.Left;
+			path.Transform (mx);
+			t.Graphics.DrawPath (p, path);
+			t.Graphics.DrawPath (Pens.White, path);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			p.Alignment = PenAlignment.Inset;
+			path.Transform (mx);
+			t.Graphics.DrawPath (p, path);
+			t.Graphics.DrawPath (Pens.White, path);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			p.Alignment = PenAlignment.Outset;
+			path.Transform (mrx);
+			path.Transform (my);
+			t.Graphics.DrawPath (p, path);
+			t.Graphics.DrawPath (Pens.White, path);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			p.Alignment = PenAlignment.Right;
+			path.Transform (mx);
+			t.Graphics.DrawPath (p, path);
+			t.Graphics.DrawPath (Pens.White, path);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+		}
+		[Test]
+		public void ColorTest () {
+			Assert.AreEqual (Color.Blue, p.Color);
+			t.Graphics.DrawLine (p, 0, 0, 200, 200);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			p.Color = Color.Red;
+			t.Graphics.DrawLine (p, 0, 0, 200, 200);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			p.Color = Color.BurlyWood;
+			t.Graphics.DrawLine (p, 0, 0, 200, 200);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			p.Color = Color.FromArgb (100, 120, 255);
+			t.Graphics.DrawLine (p, 0, 0, 200, 200);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			p.Color = Color.FromArgb (128, Color.White);
+			t.Graphics.DrawLine (p, 0, 200, 200, 0);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+		}
+		[Test]
+		public void MitterLimit () {
+			p.LineJoin = LineJoin.MiterClipped;
+			Point [] points = new Point [] {new Point (0,30), new Point (180, 31),
+											   new Point (0, 90)};
+
+			Assert.AreEqual (10F, p.MiterLimit);
+			t.Graphics.DrawLines (p, points);
+			t.Graphics.DrawLines (Pens.White, points);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+
+			Matrix dy = new Matrix (1, 0, 0, 1, 0, 110);
+			dy.TransformPoints (points);
+			p.MiterLimit=1F;
+			t.Graphics.DrawLines (p, points);
+			t.Graphics.DrawLines (Pens.White, points);
+			t.Show ();
+			Assert.IsTrue (t.Compare (10));
+		}
+		[Test]
+		public void Transform () {
+			p.ScaleTransform (0.5F, 2);
+			t.Graphics.DrawArc (p, 0, 0, 100, 100, 0, 360);
+			t.Graphics.DrawArc (Pens.White, 0, 0, 100, 100, 0, 360);
+			t.Show ();
+		}
+	}
+}

+ 214 - 0
mcs/class/System.Drawing/Test/DrawingTest/Test/Region.cs

@@ -0,0 +1,214 @@
+using System;
+using NUnit.Framework;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using DrawingTestHelper;
+
+namespace Test.Sys.Drawing {
+	[TestFixture]
+	public class RegionFixture {
+		DrawingTest t;
+		RectangleF rect;
+		Region r;
+		[SetUp]
+		public void SetUp ()
+		{
+			t = DrawingTest.Create (1000, 1000);
+			rect = new RectangleF (50, 50, 50, 50);
+			r = new Region(rect);
+		}
+		[Test]
+		public void ctor_RegionData () {
+			RegionData rgnData = r.GetRegionData ();
+			Region r1 = new Region (rgnData);
+			Assert.AreEqual (rgnData.Data, r1.GetRegionData ().Data);
+		}
+		[Test]
+		public void ctor_GraphicsPath () {
+			GraphicsPath path = new GraphicsPath ();
+			path.AddRectangle (rect);
+			Region r1 = new Region (path);
+			r1.Xor (r);
+			Assert.IsTrue (r1.IsEmpty (t.Graphics));
+		}
+		[Test]
+		public void ctor_Rectangle () {
+			Region r1 = new Region (new Rectangle ((int)rect.X, (int)rect.Y,
+				(int)rect.Width, (int)rect.Height));
+			Assert.AreEqual (r.GetRegionData ().Data,
+				r1.GetRegionData ().Data);
+		}
+		[Test]
+		public void ctor_RectangleF () {
+			Region r1 = new Region (rect);
+			Assert.AreEqual (r.GetRegionData ().Data,
+				r1.GetRegionData ().Data);
+		}
+		[Test]
+		public void ctor_void () {
+			Region r1 = new Region ();
+			Assert.IsTrue (r1.IsInfinite (t.Graphics));
+		}
+		[Test]
+		public void Clone () {
+			Region r1 = r.Clone ();
+			Assert.IsFalse (Object.ReferenceEquals (r1, r));
+			Assert.AreEqual (r1.GetBounds (t.Graphics), r.GetBounds (t.Graphics));
+            r1.Xor (r);
+			Assert.IsTrue (r1.IsEmpty (t.Graphics));
+			Assert.IsFalse (r.IsEmpty (t.Graphics));
+		}
+		[Test]
+		public void Complement () {
+			r.Complement (new Rectangle (70, 70, 80, 20));
+			Assert.AreEqual (new RectangleF (100, 70, 50, 20), 
+				r.GetBounds (t.Graphics));
+		}
+		[Test]
+		public void Equals_Graphics () {
+			Region r1 = new Region (rect);
+			Assert.IsTrue (r.Equals (r1, t.Graphics));
+		}
+		[Test]
+		public void Exclude () {
+			r.Exclude (new Rectangle (10, 10, 90, 60));
+			Assert.AreEqual (new RectangleF (50, 70, 50, 30),
+				r.GetBounds (t.Graphics));
+		}
+		[Test]
+		public void GetBounds ()
+		{
+			Assert.AreEqual (rect, r.GetBounds (t.Graphics));
+		}
+		[Test]
+		public void GetRegionData () {
+			byte [] actual = r.GetRegionData ().Data;
+			byte [] expected = new byte [] {28, 0, 0, 0, 186, 15, 11, 58, 1, 16,
+				192, 219, 0, 0, 0, 0, 0, 0, 0, 16,
+				0, 0, 72, 66, 0, 0, 72, 66, 0, 0,
+				72, 66, 0, 0, 72, 66};
+			Assert.AreEqual (expected, actual);
+		}
+		[Test]
+		public void GetRegionScans () {
+			Assert.AreEqual (new RectangleF [] {new Rectangle (50, 50, 50, 50)},
+				r.GetRegionScans (new Matrix ()));
+			r.Union (new Rectangle (100, 100, 50, 50));
+			RectangleF [] rs = new RectangleF [] {
+					new Rectangle (50, 50, 50, 50),
+					new Rectangle (100, 100, 50, 50)}; 
+			Assert.AreEqual (rs,
+				r.GetRegionScans (new Matrix ()));
+		}
+		[Test]
+		public void Intersect () {
+			r.Intersect (new Rectangle (70, 70, 50, 50));
+			Assert.AreEqual (new RectangleF (70, 70, 30, 30), 
+				r.GetBounds (t.Graphics));
+		}
+		[Test]
+		public void IsEmpty () {
+			Assert.IsFalse (r.IsEmpty (t.Graphics));
+			r.Xor (r.Clone ());
+			Assert.IsTrue (r.IsEmpty (t.Graphics));
+		}
+		[Test]
+		public void IsInfinite () {
+			Assert.IsFalse (r.IsInfinite (t.Graphics));
+            r.MakeInfinite ();
+			Assert.IsTrue (r.IsInfinite (t.Graphics));
+			RectangleF infiniteRect = new RectangleF (-0x400000, -0x400000, 0x800000, 0x800000);
+			Assert.AreEqual (new RectangleF [] {infiniteRect},
+				r.GetRegionScans (new Matrix ()));
+			r.Exclude (new Rectangle (10, 10, 10, 10));
+			Assert.IsFalse (r.IsInfinite (t.Graphics));
+			Assert.AreEqual (infiniteRect, r.GetBounds (t.Graphics));
+		}
+		[Test]
+		public void IsVisible_int () {
+			Rectangle rectD = new Rectangle (50, 50, 10000, 10000);
+			r = new Region (rectD);
+			Assert.IsTrue (r.IsVisible (rectD, t.Graphics));
+			Assert.IsTrue (r.IsVisible (rectD.X, rectD.Y, rectD.Height, rectD.Width,
+				t.Graphics));
+			Assert.IsTrue (r.IsVisible (rectD));
+			Assert.IsTrue (r.IsVisible (rectD.X, rectD.Y, rectD.Height, rectD.Width));
+			Assert.IsFalse (r.IsVisible (new Point (rectD.Right, rectD.Bottom),
+				t.Graphics));
+			Assert.IsTrue (r.IsVisible (new Point (rectD.X, rectD.Y)));
+			Assert.IsFalse (r.IsVisible (new Point (rectD.X-1, rectD.Y-1)));
+			Assert.IsTrue (r.IsVisible (100, 100, t.Graphics));
+			Assert.IsTrue (r.IsVisible (100, 100));
+		}
+		[Test]
+		[Category ("NotWorking")]
+		public void IsVisible_float () {
+			t.Graphics.PageScale = 10;
+			rect = new Rectangle (50, 50, 1000, 1000);
+			r = new Region (rect);
+			Assert.IsTrue (r.IsVisible (rect, t.Graphics));
+			Assert.IsTrue (r.IsVisible (rect.X, rect.Y, rect.Height, rect.Width,
+				t.Graphics));
+			Assert.IsTrue (r.IsVisible (rect));
+			Assert.IsTrue (r.IsVisible (rect.X, rect.Y, rect.Height, rect.Width));
+			Assert.IsFalse (r.IsVisible (new PointF (rect.Right, rect.Bottom),
+				t.Graphics));
+			Assert.IsFalse (r.IsVisible (new PointF (rect.Right, rect.Bottom)));
+			Assert.IsFalse (r.IsVisible (new PointF (rect.Right-0.1F,
+				rect.Bottom-0.1F)));
+			Assert.IsTrue (r.IsVisible (new PointF (rect.Right-1,
+				rect.Bottom-1)));
+			Assert.IsTrue (r.IsVisible (100.0F, 100.0F, t.Graphics));
+			Assert.IsTrue (r.IsVisible (100.0F, 100.0F));
+			Assert.IsTrue (r.IsVisible (new PointF (rect.X, rect.Y)));
+			Assert.IsFalse (r.IsVisible (new PointF (rect.X-0.4F,
+				rect.Y-0.4F)));
+		}
+		[Test]
+		public void MakeEmpty () {
+			Assert.IsFalse (r.IsEmpty (t.Graphics));
+			r.MakeEmpty ();
+			Assert.IsTrue (r.IsEmpty (t.Graphics));
+			Assert.AreEqual (new RectangleF (0,0,0,0),	r.GetBounds (t.Graphics));
+			Assert.IsFalse (r.IsVisible (new Rectangle (0, 0, 0, 0)));
+		}
+		[Test]
+		public void MakeInfinite () {
+			Assert.IsFalse (r.IsInfinite (t.Graphics));
+			r.MakeInfinite ();
+			Assert.IsTrue (r.IsInfinite (t.Graphics));
+			RectangleF infiniteRect = new RectangleF (-0x400000, -0x400000, 0x800000, 0x800000);
+			Assert.AreEqual (new RectangleF [] {infiniteRect},
+				r.GetRegionScans (new Matrix ()));
+		}
+		[Test]
+		public new void ToString () {
+			Assert.AreEqual ("System.Drawing.Region", r.ToString ());
+		}
+		[Test]
+		public void Transform () {
+		}
+		[Test]
+		public void Translate () {
+		}
+		[Test]
+		public void Union () {
+			r.Union (new Rectangle (70, 70, 100, 100));
+			RectangleF [] rs = new RectangleF [] {
+				new RectangleF (50, 50, 50, 20),
+				new RectangleF (50, 70, 120, 30),
+				new RectangleF (70, 100, 100, 70)};
+			Assert.AreEqual (rs, r.GetRegionScans (new Matrix()));
+		}
+		[Test]
+		public void Xor () {
+			r.Xor (new Rectangle (0, 0, 70, 70));
+			RectangleF [] rs = new RectangleF [] {
+				new RectangleF (0, 0, 70, 50),
+				new RectangleF (0, 50, 50, 20),
+				new RectangleF (70, 50, 30, 20),
+				new RectangleF (50, 70, 50, 30)};
+			Assert.AreEqual (rs, r.GetRegionScans (new Matrix()));
+		}
+	}
+}

BIN
mcs/class/System.Drawing/Test/DrawingTest/Test/SampIcon.ico


+ 335 - 0
mcs/class/System.Drawing/Test/DrawingTest/Test/Test.dotnet.csproj

@@ -0,0 +1,335 @@
+<VisualStudioProject>
+    <CSHARP
+        ProjectType = "Local"
+        ProductVersion = "7.10.3077"
+        SchemaVersion = "2.0"
+        ProjectGuid = "{DFE29E81-D6A8-45D4-A627-161F462BE767}"
+        SccProjectName = "System.Drawing.Test"
+        SccLocalPath = ".."
+        SccProvider = "MSSCCI:ClearCase"
+    >
+        <Build>
+            <Settings
+                ApplicationIcon = ""
+                AssemblyKeyContainerName = ""
+                AssemblyName = "Test.dotnet"
+                AssemblyOriginatorKeyFile = ""
+                DefaultClientScript = "JScript"
+                DefaultHTMLPageLayout = "Grid"
+                DefaultTargetSchema = "IE50"
+                DelaySign = "false"
+                OutputType = "Library"
+                PreBuildEvent = ""
+                PostBuildEvent = ""
+                RootNamespace = "Test.dotnet"
+                RunPostBuildEvent = "OnBuildSuccess"
+                StartupObject = ""
+            >
+                <Config
+                    Name = "Debug"
+                    AllowUnsafeBlocks = "false"
+                    BaseAddress = "285212672"
+                    CheckForOverflowUnderflow = "false"
+                    ConfigurationOverrideFile = ""
+                    DefineConstants = "DEBUG;TRACE"
+                    DocumentationFile = ""
+                    DebugSymbols = "true"
+                    FileAlignment = "4096"
+                    IncrementalBuild = "false"
+                    NoStdLib = "false"
+                    NoWarn = ""
+                    Optimize = "false"
+                    OutputPath = "bin\Debug\"
+                    RegisterForComInterop = "false"
+                    RemoveIntegerChecks = "false"
+                    TreatWarningsAsErrors = "false"
+                    WarningLevel = "4"
+                />
+                <Config
+                    Name = "Release"
+                    AllowUnsafeBlocks = "false"
+                    BaseAddress = "285212672"
+                    CheckForOverflowUnderflow = "false"
+                    ConfigurationOverrideFile = ""
+                    DefineConstants = "TRACE"
+                    DocumentationFile = ""
+                    DebugSymbols = "false"
+                    FileAlignment = "4096"
+                    IncrementalBuild = "false"
+                    NoStdLib = "false"
+                    NoWarn = ""
+                    Optimize = "true"
+                    OutputPath = "bin\Release\"
+                    RegisterForComInterop = "false"
+                    RemoveIntegerChecks = "false"
+                    TreatWarningsAsErrors = "false"
+                    WarningLevel = "4"
+                />
+            </Settings>
+            <References>
+                <Reference
+                    Name = "System"
+                    AssemblyName = "System"
+                    HintPath = "..\..\..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
+                />
+                <Reference
+                    Name = "nunit.framework"
+                    AssemblyName = "nunit.framework"
+                    HintPath = "..\..\..\..\..\..\..\..\..\Program Files\NUnit 2.2\bin\nunit.framework.dll"
+                    AssemblyFolderKey = "hklm\dn\nunit.framework"
+                />
+                <Reference
+                    Name = "System.Drawing"
+                    AssemblyName = "System.Drawing"
+                    HintPath = "..\..\..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Drawing.dll"
+                />
+                <Reference
+                    Name = "DrawingTestHelper_java"
+                    Project = "{8EF9FC71-4D70-4F89-BF4D-B83EF37D4A0C}"
+                    Package = "{83B010C7-76FC-4FAD-A26C-00D7EFE60256}"
+                />
+                <Reference
+                    Name = "Exocortex.DSP.v1.J2EE"
+                    Project = "{8D602CEF-DC13-48F1-AF0C-F6201A634FD2}"
+                    Package = "{83B010C7-76FC-4FAD-A26C-00D7EFE60256}"
+                />
+                <Reference
+                    Name = "System.Data"
+                    AssemblyName = "System.Data"
+                    HintPath = "..\..\..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
+                />
+                <Reference
+                    Name = "System.XML"
+                    AssemblyName = "System.Xml"
+                    HintPath = "..\..\..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
+                />
+            </References>
+        </Build>
+        <Files>
+            <Include>
+                <File
+                    RelPath = "AssemblyInfo.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "Bitmap1.png"
+                    BuildAction = "None"
+                />
+                <File
+                    RelPath = "SampIcon.ico"
+                    BuildAction = "None"
+                />
+                <File
+                    RelPath = "System.Drawing\Bitmap.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\Brush.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\Graphics.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\Image.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\Pen.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\Region.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestBitmap.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestBrushes.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestColor.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestFont.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestImageFormatConverter.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestPens.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestPoint.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestPointConverter.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestPointF.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestRectangle.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestRectangleConverter.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestRectangleF.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestRegion.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestSize.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestSizeConverter.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestSizeF.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestStringFormat.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestSystemBrushes.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\TestSystemPens.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\bitmaps\almogaver1bit.bmp"
+                    BuildAction = "Content"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\bitmaps\almogaver24bits.bmp"
+                    BuildAction = "Content"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\bitmaps\almogaver24bits1.bmp"
+                    BuildAction = "Content"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\bitmaps\almogaver32bits.bmp"
+                    BuildAction = "Content"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\bitmaps\almogaver8bits.bmp"
+                    BuildAction = "Content"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\bitmaps\almogaver-os2.bmp"
+                    BuildAction = "Content"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\bitmaps\maketransparent.bmp"
+                    BuildAction = "Content"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\bitmaps\nature24bits.gif"
+                    BuildAction = "Content"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\bitmaps\nature24bits.jpg"
+                    BuildAction = "Content"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\bitmaps\smiley.ico"
+                    BuildAction = "Content"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\bitmaps\VisualPng.ico"
+                    BuildAction = "Content"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing\bitmaps\VisualPng1.ico"
+                    BuildAction = "Content"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing.Drawing2D\TestBlend.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing.Drawing2D\TestColorBlend.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing.Drawing2D\TestHatchBrush.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing.Imaging\TestColorMatrix.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing.Imaging\TestImageAttributes.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing.Imaging\TestImageCodecInfo.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "System.Drawing\MonoTests\System.Drawing.Imaging\TestJpegCodec.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+            </Include>
+        </Files>
+    </CSHARP>
+</VisualStudioProject>
+

+ 76 - 0
mcs/class/System.Drawing/Test/DrawingTest/Test/Test.vmwcsproj

@@ -0,0 +1,76 @@
+<VisualStudioProject>
+	<CSHARP ProjectType="Local" ProductVersion="7.10.3077" SchemaVersion="2.0" ProjectGuid="{D92997D0-B8BD-49A8-A7D0-8B6043930A07}" SccProjectName="System.Drawing.Test" SccLocalPath=".." SccProvider="MSSCCI:ClearCase">
+		<Build>
+			<Settings ApplicationIcon="" AssemblyKeyContainerName="" AssemblyName="Test" AssemblyOriginatorKeyFile="" DefaultClientScript="JScript" DefaultHTMLPageLayout="Grid" DefaultTargetSchema="IE50" DelaySign="false" OutputType="Library" PreBuildEvent="" PostBuildEvent="" RootNamespace="Test" RunPostBuildEvent="OnBuildSuccess" StartupObject="">
+				<Config Name="Debug_Java" AllowUnsafeBlocks="false" BaseAddress="285212672" CheckForOverflowUnderflow="false" ConfigurationOverrideFile="" DefineConstants="DEBUG;TRACE;TARGET_JVM" DocumentationFile="" DebugSymbols="true" FileAlignment="4096" IncrementalBuild="false" NoStdLib="false" NoWarn="1595" Optimize="false" OutputPath="bin\Debug_Java\" RegisterForComInterop="false" RemoveIntegerChecks="false" TreatWarningsAsErrors="false" WarningLevel="4"/>
+				<Config Name="Release_Java" AllowUnsafeBlocks="false" BaseAddress="285212672" CheckForOverflowUnderflow="false" ConfigurationOverrideFile="" DefineConstants="TRACE;JAVA" DocumentationFile="" DebugSymbols="false" FileAlignment="4096" IncrementalBuild="false" NoStdLib="false" NoWarn="1595" Optimize="true" OutputPath="bin\Release_Java\" RegisterForComInterop="false" RemoveIntegerChecks="false" TreatWarningsAsErrors="false" WarningLevel="4"/>
+				<Config Name="Debug" AllowUnsafeBlocks="false" BaseAddress="285212672" CheckForOverflowUnderflow="false" ConfigurationOverrideFile="" DefineConstants="DEBUG;TRACE;JAVA" DocumentationFile="" DebugSymbols="true" FileAlignment="4096" IncrementalBuild="false" NoStdLib="false" NoWarn="1595" Optimize="false" OutputPath="bin\Debug\" RegisterForComInterop="false" RemoveIntegerChecks="false" TreatWarningsAsErrors="false" WarningLevel="4"/>
+			</Settings>
+			<References>
+				<Reference Name="System" AssemblyName="System" HintPath="..\..\..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"/>
+				<Reference Name="rt" AssemblyName="rt" HintPath="..\..\..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE\jgac\j2sdk1.4\rt.dll" Private="False"/>
+				<Reference Name="DrawingTestHelper_java" Project="{8EF9FC71-4D70-4F89-BF4D-B83EF37D4A0C}" Package="{83B010C7-76FC-4FAD-A26C-00D7EFE60256}"/>
+				<Reference Name="System.Drawing" AssemblyName="System.Drawing" HintPath="..\..\..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Drawing.dll" Private="False"/>
+				<Reference Name="System.Data" AssemblyName="System.Data" HintPath="..\..\..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"/>
+				<Reference Name="System.Xml" AssemblyName="System.Xml" HintPath="..\..\..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Xml.dll"/>
+				<Reference Name="nunit.core.dll.J2EE" Project="{7C52A6A5-71ED-4468-9564-2FF5CD6E6E6C}" Package="{83B010C7-76FC-4FAD-A26C-00D7EFE60256}"/>
+				<Reference Name="nunit.framework.dll.J2EE" Project="{39CC8FF7-EF1A-41A1-B727-42684211ECD1}" Package="{83B010C7-76FC-4FAD-A26C-00D7EFE60256}"/>
+				<Reference Name="nunit.util.dll.J2EE" Project="{36BE0465-4DE4-44CE-AF8D-6E50D0C40BC6}" Package="{83B010C7-76FC-4FAD-A26C-00D7EFE60256}"/>
+			</References>
+		</Build>
+		<Files>
+			<Include>
+				<File RelPath="AssemblyInfo.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="Bitmap1.png" BuildAction="None"/>
+				<File RelPath="SampIcon.ico" BuildAction="Content"/>
+				<File RelPath="System.Drawing\Bitmap.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\Brush.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\Graphics.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\Image.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\Pen.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\Region.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestBitmap.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestBrushes.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestColor.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestFont.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestIcon.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestImageFormatConverter.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestPens.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestPoint.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestPointConverter.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestPointF.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestRectangle.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestRectangleConverter.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestRectangleF.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestRegion.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestSize.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestSizeConverter.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestSizeF.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestStringFormat.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestSystemBrushes.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\TestSystemPens.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\bitmaps\almogaver1bit.bmp" BuildAction="Content"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\bitmaps\almogaver24bits.bmp" BuildAction="Content"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\bitmaps\almogaver24bits1.bmp" BuildAction="Content"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\bitmaps\almogaver32bits.bmp" BuildAction="Content"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\bitmaps\almogaver8bits.bmp" BuildAction="Content"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\bitmaps\almogaver-os2.bmp" BuildAction="Content"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\bitmaps\maketransparent.bmp" BuildAction="Content"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\bitmaps\nature24bits.gif" BuildAction="Content"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\bitmaps\nature24bits.jpg" BuildAction="Content"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\bitmaps\smiley.ico" BuildAction="Content"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\bitmaps\VisualPng.ico" BuildAction="Content"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing\bitmaps\VisualPng1.ico" BuildAction="Content"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing.Drawing2D\TestBlend.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing.Drawing2D\TestColorBlend.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing.Drawing2D\TestHatchBrush.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing.Imaging\TestColorMatrix.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing.Imaging\TestImageAttributes.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing.Imaging\TestImageCodecInfo.cs" SubType="Code" BuildAction="Compile"/>
+				<File RelPath="System.Drawing\MonoTests\System.Drawing.Imaging\TestJpegCodec.cs" SubType="Code" BuildAction="Compile"/>
+				<Folder RelPath="System.Drawing\MonoTests\System.Drawing.Text\"/>
+			</Include>
+		</Files>
+		<UserProperties REFS.JarPath.nunit.util="..\..\..\..\..\..\..\..\DevQA\studio\GH\DevQA\tests\utils\nunit\nunit-2.2.0\nunit-console\bin\Debug_Java\nunit.util.jar" REFS.JarPath.nunit.core="..\..\..\..\..\..\..\..\DevQA\studio\GH\DevQA\tests\utils\nunit\nunit-2.2.0\nunit-console\bin\Debug_Java\nunit.core.jar" REFS.JarPath.nunit.framework="..\..\..\..\..\..\..\..\DevQA\studio\GH\DevQA\tests\utils\nunit\nunit-2.2.0\nunit-console\bin\Debug_Java\nunit.framework.jar" jarserver="ipa" project.JDKType="1.4.2_05" REFS.JarPath.rt="..\..\..\..\..\..\..\..\..\j2sdk1.4\lib\rt.jar" REFS.JarPath.system.xml="..\..\..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE\jgac\vmw4j2ee_110\System.Xml.jar" REFS.JarPath.system.data="..\..\..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE\jgac\vmw4j2ee_110\System.Data.jar" REFS.JarPath.system="..\..\..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE\jgac\vmw4j2ee_110\System.jar" REFS.JarPath.system.drawing="..\..\..\..\..\..\..\..\..\Program Files\Mainsoft\Visual MainWin for J2EE\jgac\vmw4j2ee_110\System.Drawing.jar"/>
+	</CSHARP>
+	<VisualMainWin><Project Prop2023="1.4.2_05" Prop2024="" Prop2026="" Prop2015="" Version="1.6.0" ProjectType="1"/><References/><Configs><Config Prop2000="0" Prop2001="0" Prop2002="0" Prop2003="0" Prop2004="0" Prop2005="1" Prop2006="C:\views\DevQA\studio\GH\DevQA\tests\utils\nunit\nunit-2.2.0\nunit-console\bin\Debug_Java\nunit-console.jar" Prop2007="" Prop2008="" Prop2009="Test.jar /wait /fixture:MonoTests.System.Drawing" Prop2010="" Prop2011="-1" Prop2012="0" Prop2013="" Prop2014="0" Prop2016="" Prop2027="" Prop2019="0" Prop2020="285212672" Prop2021="4096" Prop2022="0" Prop2017="0" Prop2018="-1" Name="Debug_Java"/><Config Prop2000="1" Prop2001="0" Prop2002="0" Prop2003="0" Prop2004="0" Prop2005="1" Prop2006="C:\Program Files\NUnit 2.2\bin\nunit-gui.exe" Prop2007="" Prop2008="" Prop2009="Test.dll" Prop2010="" Prop2011="-1" Prop2012="0" Prop2013="" Prop2014="0" Prop2016="" Prop2027="" Prop2019="0" Prop2020="285212672" Prop2021="4096" Prop2022="0" Prop2017="0" Prop2018="0" Name="Debug"/><Config Prop2000="0" Prop2001="0" Prop2002="0" Prop2003="0" Prop2004="0" Prop2005="0" Prop2006="" Prop2007="" Prop2008="" Prop2009="" Prop2010="" Prop2011="-1" Prop2012="0" Prop2013="" Prop2014="0" Prop2016="" Prop2027="" Prop2019="0" Prop2020="285212672" Prop2021="4096" Prop2022="0" Prop2017="0" Prop2018="0" Name="Release_Java"/></Configs></VisualMainWin></VisualStudioProject>