svn path=/branches/mono-1-1-9/mcs/; revision=50438
[mono.git] / mcs / class / System.Drawing / Test / DrawingTest / DrawingTestHelper / DrawingTest.cs
1 using System;\r
2 using System.Drawing;\r
3 using System.Diagnostics;\r
4 using System.IO;\r
5 using System.Text;\r
6 using Exocortex.DSP;\r
7 using System.Reflection;\r
8 using System.Xml.Serialization;\r
9 using System.Collections;\r
10 using System.Security.Cryptography;\r
11 \r
12 #if TARGET_JVM\r
13 using awt = java.awt;\r
14 using javax.imageio;\r
15 using java.lang;\r
16 using java.security;\r
17 using java.awt.image;\r
18 #else\r
19 using System.Windows.Forms;\r
20 using System.Drawing.Imaging;\r
21 using System.Runtime.InteropServices;\r
22 #endif\r
23 \r
24 using NUnit.Framework;\r
25 \r
26 namespace DrawingTestHelper\r
27 {\r
28         #region Results serialization classes\r
29         public sealed class ExpectedResult {\r
30                 public ExpectedResult(){}\r
31                 public ExpectedResult(string testName, double norm) {\r
32                         TestName = testName;\r
33                         Norm = norm;\r
34                 }\r
35                 public string TestName;\r
36                 public double Norm;\r
37         }\r
38 \r
39         public sealed class ExpectedResults {\r
40                 [XmlArrayItem(typeof(ExpectedResult))]\r
41                 public ArrayList Tests = new ArrayList();\r
42         }\r
43 \r
44         public sealed class ExpectedResultsHash {\r
45                 Hashtable _hash;\r
46                 ExpectedResults _suite;\r
47 \r
48                 public ExpectedResultsHash () {\r
49                         try {\r
50                                 using (StreamReader s = new StreamReader (FileName)) {\r
51                                         _suite = (ExpectedResults)TestSuiteSerializer.Deserialize(s);\r
52                                 }\r
53                         }\r
54                         catch {\r
55                                 _suite = new ExpectedResults ();\r
56                         }\r
57                         _hash = new Hashtable(_suite.Tests.Count);\r
58                         foreach (ExpectedResult res in _suite.Tests)\r
59                                 _hash[res.TestName] = res.Norm;\r
60                 }\r
61 \r
62                 public const string FileName = "ExpectedResults.xml";\r
63                 public readonly static XmlSerializer TestSuiteSerializer = new XmlSerializer(typeof(ExpectedResults));\r
64 \r
65                 public double GetNorm(string testName) {\r
66                         object res = _hash[testName];\r
67                         if (res != null)\r
68                                 return (double)res;\r
69                         return double.NaN;\r
70                 }\r
71 \r
72                 public void WriteNorm (string testName, double myNorm) {\r
73                         if (_hash.Contains (testName)) {\r
74                                 for (int i = 0; i < _suite.Tests.Count; i++) {\r
75                                         ExpectedResult cur = (ExpectedResult) _suite.Tests[i];\r
76                                         if (cur.TestName == testName) {\r
77                                                 cur.Norm = myNorm;\r
78                                                 break;\r
79                                         }\r
80                                 }\r
81                         }\r
82                         else\r
83                                 _suite.Tests.Add(new ExpectedResult(testName, myNorm));\r
84 \r
85                         _hash[testName] = myNorm;\r
86                         using(StreamWriter w = new StreamWriter(FileName))\r
87                                 TestSuiteSerializer.Serialize(w, _suite);\r
88                 }\r
89         }\r
90 \r
91         public sealed class CachedResult {\r
92                 public CachedResult (){}\r
93                 public CachedResult (string testName, string sha1, double norm) {\r
94                         TestName = testName;\r
95                         SHA1 = sha1;\r
96                         Norm = norm;\r
97                         DateTime = DateTime.Now;\r
98                 }\r
99 \r
100                 public string TestName;\r
101                 public string SHA1;\r
102                 public double Norm;\r
103                 public DateTime DateTime;\r
104         }\r
105 \r
106         public sealed class CachedResults {\r
107                 [XmlArrayItem(typeof(CachedResult))]\r
108                 public ArrayList Tests = new ArrayList();\r
109         }\r
110 \r
111         public class Cache {\r
112                 Hashtable _hash;\r
113                 CachedResults _results;\r
114 \r
115 #if TARGET_JVM\r
116                 public const string FileName = "CachedResults.xml";\r
117                 public const string NewFileName = "NewCachedResults.xml";\r
118 #else\r
119                 public const string FileName = "dotnet.CachedResults.xml";\r
120                 public const string NewFileName = "dotnet.NewCachedResults.xml";\r
121 #endif\r
122                 public readonly static XmlSerializer TestSuiteSerializer =\r
123                         new XmlSerializer(typeof(CachedResults));\r
124 \r
125                 public Cache () {\r
126                         try {\r
127                                 using (StreamReader r = new StreamReader(FileName))\r
128                                         _results = (CachedResults)TestSuiteSerializer.Deserialize(r);\r
129                         }\r
130                         catch {\r
131                                 _results = new CachedResults ();\r
132                         }\r
133                         \r
134                         _hash = new Hashtable(_results.Tests.Count);\r
135                         foreach (CachedResult res in _results.Tests)\r
136                                 _hash[res.SHA1] = res.Norm;\r
137                 }\r
138 \r
139                 public double GetNorm (string sha1) {\r
140                         if (_hash.ContainsKey (sha1))\r
141                                 return (double)_hash[sha1];\r
142                         else\r
143                                 return double.NaN;\r
144                 }\r
145 \r
146                 public void Add (string testName, string sha1, double norm) {\r
147                         if (_hash.ContainsKey (sha1))\r
148                                 throw new ArgumentException ("This SHA1 is already in the cache", "sha1");\r
149 \r
150                         _results.Tests.Add (new CachedResult(testName, sha1, norm));\r
151                         _hash.Add (sha1, norm);\r
152 \r
153                         using(StreamWriter w = new StreamWriter(NewFileName))\r
154                                 TestSuiteSerializer.Serialize(w, _results);\r
155                 }\r
156         }\r
157         #endregion\r
158 \r
159         /// <summary>\r
160         /// Summary description for DrawingTest.\r
161         /// </summary>\r
162         public abstract class DrawingTest {\r
163 \r
164                 public const float DEFAULT_FLOAT_TOLERANCE = 1e-5f; \r
165                 public const int DEFAULT_IMAGE_TOLERANCE = 2; \r
166 \r
167                 Graphics _graphics;\r
168                 protected Bitmap _bitmap;\r
169                 static string _callingFunction;\r
170                 //static int _counter;\r
171                 static Hashtable _mpFuncCount = new Hashtable();\r
172                 static bool _showForms = false;\r
173                 static bool _createResults = true;\r
174                 protected string _ownerClass = "";\r
175                 protected Hashtable _specialTolerance = null;\r
176 \r
177                 protected readonly static ExpectedResultsHash ExpectedResults = new ExpectedResultsHash ();\r
178                 protected readonly static Cache cache = new Cache ();\r
179 \r
180                 public Graphics Graphics {get {return _graphics;}}\r
181                 public Bitmap Bitmap {get { return _bitmap; }}\r
182 \r
183                 public Hashtable SpecialTolerance \r
184                 {\r
185                         get {return _specialTolerance;}\r
186                         set {_specialTolerance = value;}\r
187                 }\r
188 \r
189                 public string OwnerClass \r
190                 {\r
191                         get {return _ownerClass;}\r
192                         set {_ownerClass = value;}\r
193                 }\r
194 \r
195                 public static bool ShowForms \r
196                 {\r
197                         get {return _showForms;}\r
198                         set {_showForms = value;}\r
199                 }\r
200 \r
201                 public static bool CreateResults {\r
202                         get {return _createResults;}\r
203                         set {_createResults = value;}\r
204                 }\r
205 \r
206                 protected DrawingTest() {}\r
207                 \r
208                 private void Init (int width, int height) {\r
209                         Init (new Bitmap (width, height));\r
210                 }\r
211 \r
212                 private void Init (Bitmap bitmap) {\r
213                         _bitmap = bitmap;\r
214                         _graphics = Graphics.FromImage (_bitmap);\r
215                 }\r
216 \r
217                 protected abstract string DetermineCallingFunction ();\r
218 \r
219                 protected interface IMyForm {\r
220                         void Show ();\r
221                 }\r
222 \r
223                 protected abstract IMyForm CreateForm (string title);\r
224 \r
225                 public void Show () {\r
226                         CheckCounter ();\r
227                         if (!ShowForms)\r
228                                 return;\r
229                         IMyForm form = CreateForm(_callingFunction + _mpFuncCount[_callingFunction]);\r
230                         form.Show ();\r
231                 }\r
232         \r
233                 static protected string TestName {\r
234                         get {\r
235                                 return _callingFunction + ":" + _mpFuncCount[_callingFunction]/* + ".dat"*/;\r
236                         }\r
237                 }\r
238 \r
239                 #region GetImageFFTArray\r
240                 private static ComplexF[] GetImageFFTArray(Bitmap bitmap) {\r
241                         float scale = 1F / (float) System.Math.Sqrt(bitmap.Width * bitmap.Height);\r
242                         ComplexF[] data = new ComplexF [bitmap.Width * bitmap.Height * 4];\r
243 \r
244                         int offset = 0;\r
245                         for( int y = 0; y < bitmap.Height; y ++ )\r
246                                 for( int x = 0; x < bitmap.Width; x ++ ) {\r
247                                         Color c = bitmap.GetPixel (x, y);\r
248                                         float s = 1F;\r
249                                         if( (( x + y ) & 0x1 ) != 0 ) {\r
250                                                 s = -1F;\r
251                                         }\r
252 \r
253                                         data [offset++] = new ComplexF( c.A * s / 256F, 0);\r
254                                         data [offset++] = new ComplexF( c.R * s / -256F, 0);\r
255                                         data [offset++] = new ComplexF( c.G * s / 256F, 0);\r
256                                         data [offset++] = new ComplexF( c.B * s / -256F, 0);\r
257                                 }\r
258                         \r
259 \r
260                         Fourier.FFT3( data, 4, bitmap.Width, bitmap.Height, FourierDirection.Forward );\r
261                         \r
262                         for( int i = 0; i < data.Length; i ++ ) {\r
263                                 data[i] *= scale;\r
264                         }\r
265 \r
266                         return data;\r
267                 }\r
268                 #endregion\r
269 \r
270                 abstract public string CalculateSHA1 ();\r
271                 \r
272                 public static double CalculateNorm (Bitmap bitmap) {\r
273                         ComplexF[] matrix = GetImageFFTArray(bitmap);\r
274 \r
275                         double norm = 0;\r
276                         int size_x = 4; //ARGB values\r
277                         int size_y = bitmap.Width;\r
278                         int size_z = bitmap.Height;\r
279                         for (int x=1; x<=size_x; x++) {\r
280                                 double norm_y = 0;\r
281                                 for (int y=1; y<=size_y; y++) {\r
282                                         double norm_z = 0;\r
283                                         for (int z=1; z<=size_z; z++) {\r
284                                                 ComplexF cur = matrix[(size_x-x)+size_x*(size_y-y)+size_x*size_y*(size_z-z)];\r
285                                                 norm_z += cur.GetModulusSquared ();// * z;\r
286                                         }\r
287                                         norm_y += norm_z;// * y;\r
288                                 }\r
289                                 norm += norm_y;// * x;\r
290                         }\r
291                         return norm;\r
292                 }\r
293 \r
294                 public double GetNorm () {\r
295                         string sha1 = CalculateSHA1 ();\r
296 \r
297                         double norm = cache.GetNorm (sha1);\r
298                         if (double.IsNaN (norm)) {\r
299                                 norm = CalculateNorm (_bitmap);\r
300                                 cache.Add (TestName, sha1, norm);\r
301                                 //_bitmap.Save(TestName.Replace(":", "_"));\r
302                         }\r
303                         return norm;\r
304                 }\r
305 \r
306                 protected abstract double GetExpectedNorm (double myNorm);\r
307 \r
308                 private void CheckCounter () {\r
309                         string callFunc = DetermineCallingFunction ();\r
310                         _callingFunction = callFunc;\r
311                         if (!_mpFuncCount.Contains(_callingFunction)) {\r
312                                 \r
313                                 _mpFuncCount[_callingFunction] = 1;\r
314                         }\r
315                         else {\r
316                                 int counter = (int)_mpFuncCount[_callingFunction];\r
317                                 counter ++;\r
318                                 _mpFuncCount[_callingFunction] = counter;\r
319                         }\r
320                 }\r
321 \r
322                 public static void AssertAlmostEqual (float expected, float actual)\r
323                 {\r
324                         AssertAlmostEqual (expected, actual, DEFAULT_FLOAT_TOLERANCE);\r
325                 }\r
326                 \r
327                 public static void AssertAlmostEqual (float expected, float actual, float tolerance)\r
328                 {\r
329                         string msg = String.Format("\nExpected : {0} \nActual : {1}",expected.ToString(),actual.ToString());\r
330                         AssertAlmostEqual (expected, actual, tolerance, msg);\r
331                 }\r
332 \r
333                 private static void AssertAlmostEqual (float expected, float actual, float tolerance, string message)\r
334                 {\r
335                         float error = System.Math.Abs ((expected - actual) / (expected + actual + float.Epsilon));\r
336                         Assert.IsTrue (error < tolerance, message);\r
337                 }\r
338 \r
339                 public static void AssertAlmostEqual (PointF expected, PointF actual)\r
340                 {\r
341                         string msg = String.Format("\nExpected : {0} \n  Actual : {1}",expected.ToString(),actual.ToString());\r
342                         AssertAlmostEqual (expected.X, actual.X, DEFAULT_FLOAT_TOLERANCE, msg);\r
343                         AssertAlmostEqual (expected.Y, actual.Y, DEFAULT_FLOAT_TOLERANCE, msg);\r
344                 }\r
345 \r
346                 /// <summary>\r
347                 /// Checks that the given bitmap norm is similar to expected\r
348                 /// </summary>\r
349                 /// <param name="tolerance">tolerance in percents (0..100)</param>\r
350                 /// <returns></returns>\r
351                 /// \r
352                 public bool Compare (double tolerance) {\r
353                         CheckCounter ();\r
354 \r
355                         double error = CompareToExpectedInternal()*100;\r
356 \r
357                         if (SpecialTolerance != null)\r
358                                 return error <= GetSpecialTolerance(TestName);\r
359 \r
360                         return error <= tolerance;\r
361                 }\r
362 \r
363                 public bool PDCompare (double tolerance) {\r
364                         Bitmap ri = GetReferenceImage(TestName);\r
365                         if (ri == null)\r
366                                 return true;\r
367 \r
368                         double error = PDComparer.Compare(ri, _bitmap);\r
369                         return error <= tolerance;\r
370                 }\r
371                 \r
372                 public bool Compare () {\r
373                         CheckCounter ();\r
374 \r
375                         double error = CompareToExpectedInternal()*100;\r
376                         \r
377                         if (SpecialTolerance != null)\r
378                                 return error <= GetSpecialTolerance(TestName);\r
379 \r
380                         return error <= DEFAULT_IMAGE_TOLERANCE;\r
381                 }\r
382 \r
383                 public bool PDCompare () {\r
384                         Bitmap ri = GetReferenceImage(TestName);\r
385                         if (ri == null)\r
386                                 return true;\r
387 \r
388                         double error = PDComparer.Compare(ri, _bitmap);\r
389                         return error <= DEFAULT_IMAGE_TOLERANCE;\r
390                 }\r
391 \r
392                 protected abstract Bitmap GetReferenceImage(string testName);\r
393 \r
394                 protected double GetSpecialTolerance(string testName) {\r
395                         try     {\r
396                                 string shortTestName = testName.Substring( testName.LastIndexOf(".") + 1 );\r
397                                 object o = SpecialTolerance[shortTestName];\r
398                                 if (o == null)\r
399                                         return DEFAULT_IMAGE_TOLERANCE;\r
400 \r
401                                 return Convert.ToDouble(o);\r
402                         }\r
403                         catch (System.Exception) {\r
404                                 return DEFAULT_IMAGE_TOLERANCE;\r
405                         }\r
406                 }\r
407 \r
408                 public void AssertCompare () {\r
409                         CheckCounter ();\r
410                         Assert.IsTrue ((CompareToExpectedInternal () * 100) < DEFAULT_IMAGE_TOLERANCE);\r
411                 }\r
412 \r
413                 public void AssertCompare (double tolerance) {\r
414                         CheckCounter ();\r
415                         Assert.IsTrue ((CompareToExpectedInternal () * 100) < tolerance);\r
416                 }\r
417                 \r
418                 public double CompareToExpected () {\r
419                         CheckCounter ();\r
420                         return CompareToExpectedInternal ();\r
421                 }\r
422 \r
423                 double CompareToExpectedInternal () {\r
424                         if (ShowForms)\r
425                                 return 0;\r
426 \r
427                         double norm = GetNorm ();\r
428                         double expNorm = GetExpectedNorm (norm);\r
429                         return System.Math.Abs (norm-expNorm)/(norm+expNorm+double.Epsilon);\r
430                 }\r
431 \r
432                 public static DrawingTest Create (int width, int height) {\r
433                         return Create(width, height, "GraphicsFixture");\r
434                 }\r
435                 public static DrawingTest Create (int width, int height, string ownerClass) {\r
436                         DrawingTest test;\r
437 #if TARGET_JVM\r
438                         test = new JavaDrawingTest ();\r
439 #else\r
440                         test = new NetDrawingTest ();\r
441 #endif\r
442                         test.Init (width, height);\r
443                         test.OwnerClass = ownerClass;\r
444                         return test;\r
445                 }\r
446         }\r
447 \r
448 #if TARGET_JVM\r
449         internal class JavaDrawingTest:DrawingTest {\r
450                 java.awt.image.BufferedImage _image;\r
451                 java.awt.image.BufferedImage Image {\r
452                         get {\r
453                                 if (_image != null)\r
454                                         return _image;\r
455                                 Type imageType = typeof (Bitmap);\r
456                                 PropertyInfo [] props = imageType.GetProperties (\r
457                                         BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);\r
458 \r
459                                 PropertyInfo prop = null;\r
460                                 foreach (PropertyInfo p in props) {\r
461                                         if (p.Name == "NativeObject")\r
462                                                 if (p.PropertyType == typeof(java.awt.image.BufferedImage))\r
463                                                         prop = p;\r
464                                 }\r
465 \r
466                                 MethodInfo method = prop.GetGetMethod (true);\r
467                                 _image = (java.awt.image.BufferedImage) method.Invoke (_bitmap, new object [0]);\r
468                                 return _image;\r
469                         }\r
470                 }\r
471 \r
472                 public JavaDrawingTest () {}\r
473 \r
474                 protected override double GetExpectedNorm (double myNorm) {\r
475                         return ExpectedResults.GetNorm(TestName);\r
476                 }\r
477 \r
478                 protected override Bitmap GetReferenceImage(string testName) {\r
479                         try{\r
480                                 string dotNetResultsFolder = @"..\Debug\";\r
481                                 string fileName = dotNetResultsFolder + testName.Replace(":", "_") + ".png";\r
482                                 return new Bitmap(fileName);\r
483                         }\r
484                         catch(System.Exception e) {\r
485                                 throw new System.Exception("Error creating .Net reference image");\r
486                         }\r
487                 }\r
488 \r
489                 private class JavaForm:java.awt.Dialog,IMyForm {\r
490                         class EventListener : java.awt.@event.WindowListener {\r
491                                 #region WindowListener Members\r
492 \r
493                                 public void windowOpened(java.awt.@event.WindowEvent arg_0) {\r
494                                         // TODO:  Add ttt.windowOpened implementation\r
495                                 }\r
496 \r
497                                 public void windowActivated(java.awt.@event.WindowEvent arg_0) {\r
498                                         // TODO:  Add ttt.windowActivated implementation\r
499                                 }\r
500 \r
501                                 public void windowClosed(java.awt.@event.WindowEvent arg_0) {\r
502                                         // TODO:  Add ttt.windowClosed implementation\r
503                                 }\r
504 \r
505                                 public void windowDeiconified(java.awt.@event.WindowEvent arg_0) {\r
506                                         // TODO:  Add ttt.windowDeiconified implementation\r
507                                 }\r
508 \r
509                                 public void windowIconified(java.awt.@event.WindowEvent arg_0) {\r
510                                         // TODO:  Add ttt.windowIconified implementation\r
511                                 }\r
512 \r
513                                 public void windowClosing(java.awt.@event.WindowEvent arg_0) {\r
514                                         // TODO:  Add ttt.windowClosing implementation\r
515                                         java.awt.Window w = arg_0.getWindow();\r
516                                         java.awt.Window par = w.getOwner ();\r
517                                         w.dispose();\r
518                                         par.dispose ();\r
519                                 }\r
520 \r
521                                 public void windowDeactivated(java.awt.@event.WindowEvent arg_0) {\r
522                                         // TODO:  Add ttt.windowDeactivated implementation\r
523                                 }\r
524 \r
525                                 #endregion\r
526                         }\r
527 \r
528                         java.awt.Image _image;\r
529                         Size _s;\r
530 \r
531                         public JavaForm (string title, java.awt.Image anImage, Size s)\r
532                                 : base(new java.awt.Frame(), title, true) {\r
533                                 _image = anImage;\r
534                                 _s = s;\r
535                                 \r
536                                 addWindowListener(new EventListener());\r
537                         }\r
538                         public override void paint (java.awt.Graphics g) {\r
539                                 base.paint (g);\r
540                                 awt.Insets insets = this.getInsets ();\r
541                                 g.drawImage (_image, insets.left, insets.top, null);\r
542                         }\r
543                         void IMyForm.Show () {\r
544                                 awt.Insets insets = this.getInsets ();\r
545                                 base.setSize (_s.Width + insets.left + insets.right,\r
546                                         _s.Width + insets.top + insets.bottom);\r
547                                 this.show ();\r
548                                 //save the image\r
549                                 //ImageIO.write((java.awt.image.RenderedImage)_image, "png", new java.io.File("test.java.png"));\r
550                         }\r
551                 }\r
552 \r
553                 protected override IMyForm CreateForm(string title) {\r
554                         return new JavaForm (title, Image, _bitmap.Size);\r
555                 }\r
556                 \r
557                 protected override string DetermineCallingFunction() {\r
558                         System.Exception e = new System.Exception ();\r
559                         java.lang.Class c = vmw.common.TypeUtils.ToClass (e);\r
560                         java.lang.reflect.Method m = c.getMethod ("getStackTrace",\r
561                                 new java.lang.Class [0]);\r
562                         java.lang.StackTraceElement [] els = (java.lang.StackTraceElement [])\r
563                                 m.invoke (e, new object [0]);\r
564                         java.lang.StackTraceElement el = els [4];\r
565                         return el.getClassName () + "." + _ownerClass + "." + el.getMethodName ();\r
566                 }\r
567 \r
568                 public override string CalculateSHA1() {\r
569                         MessageDigest md = MessageDigest.getInstance ("SHA");\r
570                         DataBufferInt dbi = (DataBufferInt) Image.getRaster ().getDataBuffer ();\r
571                         for (int i=0; i<dbi.getNumBanks (); i++) {\r
572                                 int [] curBank = dbi.getData (i);\r
573                                 for (int j=0; j<curBank.Length; j++) {\r
574                                         int x = curBank[j];\r
575                                         md.update ((sbyte) (x & 0xFF));\r
576                                         md.update ((sbyte) ((x>>8) & 0xFF));\r
577                                         md.update ((sbyte) ((x>>16) & 0xFF));\r
578                                         md.update ((sbyte) ((x>>24) & 0xFF));\r
579                                 }\r
580                         }\r
581                         byte [] resdata = (byte[])vmw.common.TypeUtils.ToByteArray(md.digest());\r
582                         return Convert.ToBase64String (resdata);\r
583                 }\r
584         }\r
585 #else\r
586         internal class NetDrawingTest:DrawingTest {\r
587                 public NetDrawingTest () {}\r
588 \r
589                 protected override double GetExpectedNorm (double myNorm) {\r
590                         if (CreateResults)\r
591                                 ExpectedResults.WriteNorm (TestName, myNorm);\r
592 \r
593                         return myNorm;\r
594                 }\r
595 \r
596                 protected override Bitmap GetReferenceImage(string testName) {\r
597                         try{\r
598                                 string fileName = testName.Replace(":", "_") + ".png";\r
599                                 _bitmap.Save( fileName );\r
600                                 return null;\r
601                         }\r
602                         catch(System.Exception e) {\r
603                                 throw new System.Exception("Error creating .Net reference image");\r
604                         }\r
605                 }\r
606 \r
607                 private class NetForm:Form,IMyForm {\r
608                         Image image;\r
609                         public NetForm(string title, Image anImage):base() {\r
610                                 base.Text = title;\r
611                                 image = anImage;\r
612                         }\r
613                         protected override void OnPaint(PaintEventArgs e) {\r
614                                 e.Graphics.DrawImageUnscaled (image, 0, 0);\r
615                         }\r
616                         void IMyForm.Show () {\r
617                                 this.Size = image.Size;\r
618                                 this.ShowDialog ();\r
619                                 this.image.Save("test.net.png");\r
620                         }\r
621                 }\r
622                 protected override IMyForm CreateForm(string title) {\r
623                         return new NetForm (title, _bitmap);\r
624                 }\r
625 \r
626                 protected override string DetermineCallingFunction() {\r
627                         StackFrame sf = new StackFrame (3, true);\r
628                         MethodBase mb = sf.GetMethod ();\r
629 \r
630                         string name = mb.DeclaringType.FullName + "." + _ownerClass + "." + mb.Name;\r
631                         return name;\r
632                 }\r
633 \r
634                 public override string CalculateSHA1() {\r
635                         Rectangle r = new Rectangle(0, 0, _bitmap.Width, _bitmap.Height);\r
636                         \r
637                         BitmapData data = _bitmap.LockBits (r, ImageLockMode.ReadOnly,\r
638                                 _bitmap.PixelFormat);\r
639                         int dataSize = data.Stride * data.Height;\r
640                         byte [] bdata = new byte [dataSize];\r
641                         Marshal.Copy (data.Scan0, bdata, 0, dataSize);\r
642                         _bitmap.UnlockBits (data);\r
643 \r
644                         SHA1 sha1 = new SHA1CryptoServiceProvider ();\r
645                         byte [] resdata = sha1.ComputeHash (bdata);\r
646                         return Convert.ToBase64String (resdata);\r
647                 }\r
648 \r
649         }\r
650 #endif\r
651 \r
652 }\r