New test.
[mono.git] / mcs / class / System.Drawing / Test / System.Drawing / TestGraphics.cs
1 //
2 // Graphics class testing unit
3 //
4 // Authors:
5 //   Jordi Mas, jordi@ximian.com
6 //   Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 // Copyright (C) 2005-2006 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using NUnit.Framework;
31 using System;
32 using System.Drawing;
33 using System.Drawing.Text;
34 using System.Drawing.Drawing2D;
35 using System.IO;
36 using System.Reflection;
37
38 namespace MonoTests.System.Drawing
39 {
40         [TestFixture]
41         public class GraphicsTest {
42
43                 private RectangleF[] rects;
44                 private Font font;
45
46                 [TestFixtureSetUp]
47                 public void FixtureSetUp ()
48                 {
49                         try {
50                                 font = new Font ("Arial", 12);
51                         }
52                         catch {
53                         }
54                 }
55
56                 [TestFixtureTearDown]
57                 public void FixtureTearDown ()
58                 {
59                         if (font != null)
60                                 font.Dispose ();
61                 }
62                 
63
64                 private bool IsEmptyBitmap (Bitmap bitmap, out int x, out int y)
65                 {
66                         bool result = true;
67                         int empty = Color.Empty.ToArgb ();
68 #if false
69                         for (y = 0; y < bitmap.Height; y++) {
70                                 for (x = 0; x < bitmap.Width; x++) {
71                                         if (bitmap.GetPixel (x, y).ToArgb () != empty) {
72                                                 Console.Write ("X");
73                                                 result = false;
74                                         } else
75                                                 Console.Write (" ");
76                                 }
77                                 Console.WriteLine ();
78                         }
79 #else
80                         for (y = 0; y < bitmap.Height; y++) {
81                                 for (x = 0; x < bitmap.Width; x++) {
82                                         if (bitmap.GetPixel (x, y).ToArgb () != empty)
83                                                 return false;
84                                 }
85                         }
86 #endif
87                         x = -1;
88                         y = -1;
89                         return result;
90                 }
91
92                 private void CheckForEmptyBitmap (Bitmap bitmap)
93                 {
94                         int x, y;
95                         if (!IsEmptyBitmap (bitmap, out x, out y))
96                                 Assert.Fail (String.Format ("Position {0},{1}", x, y));
97                 }
98
99                 private void CheckForNonEmptyBitmap (Bitmap bitmap)
100                 {
101                         int x, y;
102                         if (IsEmptyBitmap (bitmap, out x, out y))
103                                 Assert.Fail ("Bitmap was empty");
104                 }
105
106                 private void AssertEquals (string msg, object expected, object actual)
107                 {
108                         Assert.AreEqual (expected, actual, msg);
109                 }
110
111                 private void AssertEquals (string msg, double expected, double actual, double delta)
112                 {
113                         Assert.AreEqual (expected, actual, delta, msg);
114                 }
115
116                 [Test]
117                 public void DefaultProperties ()
118                 {
119                         Bitmap bmp = new Bitmap (200, 200);
120                         Graphics g = Graphics.FromImage (bmp);
121                         Region r = new Region ();
122
123                         AssertEquals ("DefaultProperties1", r.GetBounds (g) , g.ClipBounds);
124                         AssertEquals ("DefaultProperties2", CompositingMode.SourceOver, g.CompositingMode);
125                         AssertEquals ("DefaultProperties3", CompositingQuality.Default, g.CompositingQuality);
126                         AssertEquals ("DefaultProperties4", InterpolationMode.Bilinear, g.InterpolationMode);
127                         AssertEquals ("DefaultProperties5", 1, g.PageScale);
128                         AssertEquals ("DefaultProperties6", GraphicsUnit.Display, g.PageUnit);
129                         AssertEquals ("DefaultProperties7", PixelOffsetMode.Default, g.PixelOffsetMode);
130                         AssertEquals ("DefaultProperties8", new Point (0, 0) , g.RenderingOrigin);
131                         AssertEquals ("DefaultProperties9", SmoothingMode.None, g.SmoothingMode);
132                         AssertEquals ("DefaultProperties10", TextRenderingHint.SystemDefault, g.TextRenderingHint);
133
134                         r.Dispose ();
135                 }
136                 
137                 [Test]
138                 public void SetGetProperties ()
139                 {
140                         Bitmap bmp = new Bitmap (200, 200);
141                         Graphics g = Graphics.FromImage (bmp);                                          
142                         
143                         g.CompositingMode = CompositingMode.SourceCopy;
144                         g.CompositingQuality = CompositingQuality.GammaCorrected;
145                         g.InterpolationMode = InterpolationMode.HighQualityBilinear;
146                         g.PageScale = 2;
147                         g.PageUnit = GraphicsUnit.Inch;                 
148                         g.PixelOffsetMode = PixelOffsetMode.Half;
149                         g.RenderingOrigin = new Point (10, 20);
150                         g.SmoothingMode = SmoothingMode.AntiAlias;
151                         g.TextRenderingHint = TextRenderingHint.SystemDefault;
152
153                         //Clipping set/get tested in clipping functions                 
154                         AssertEquals ("SetGetProperties2", CompositingMode.SourceCopy, g.CompositingMode);
155                         AssertEquals ("SetGetProperties3", CompositingQuality.GammaCorrected, g.CompositingQuality);
156                         AssertEquals ("SetGetProperties4", InterpolationMode.HighQualityBilinear, g.InterpolationMode);
157                         AssertEquals ("SetGetProperties5", 2, g.PageScale);
158                         AssertEquals ("SetGetProperties6", GraphicsUnit.Inch, g.PageUnit);
159                         AssertEquals ("SetGetProperties7", PixelOffsetMode.Half, g.PixelOffsetMode);
160                         AssertEquals ("SetGetProperties8", new Point (10, 20), g.RenderingOrigin);
161                         AssertEquals ("SetGetProperties9", SmoothingMode.AntiAlias, g.SmoothingMode);
162                         AssertEquals ("SetGetProperties10", TextRenderingHint.SystemDefault, g.TextRenderingHint);                      
163                 }
164
165                 // Properties
166                 [Test]
167                 public void Clip ()
168                 {
169                         RectangleF[] rects ;
170                         Bitmap bmp = new Bitmap (200, 200);
171                         Graphics g = Graphics.FromImage (bmp);
172                         g.Clip = new Region (new Rectangle (50, 40, 210, 220));
173                         rects = g.Clip.GetRegionScans (new Matrix ());
174
175                         AssertEquals ("Clip1", 1, rects.Length);
176                         AssertEquals ("Clip2", 50, rects[0].X);
177                         AssertEquals ("Clip3", 40, rects[0].Y);
178                         AssertEquals ("Clip4", 210, rects[0].Width);
179                         AssertEquals ("Clip5", 220, rects[0].Height);
180                 }
181
182                 [Test]
183                 public void Clip_NotAReference ()
184                 {
185                         Bitmap bmp = new Bitmap (200, 200);
186                         Graphics g = Graphics.FromImage (bmp);
187                         Assert.IsTrue (g.Clip.IsInfinite (g), "IsInfinite");
188                         g.Clip.IsEmpty (g);
189                         Assert.IsFalse (g.Clip.IsEmpty (g), "!IsEmpty");
190                         Assert.IsTrue (g.Clip.IsInfinite (g), "IsInfinite-2");
191                 }
192
193                 [Test]
194                 public void ExcludeClip ()
195                 {
196                         Bitmap bmp = new Bitmap (200, 200);
197                         Graphics g = Graphics.FromImage (bmp);
198
199                         g.Clip = new Region (new RectangleF (10, 10, 100, 100));
200                         g.ExcludeClip (new Rectangle (40, 60, 100, 20));
201                         rects = g.Clip.GetRegionScans (new Matrix ());
202
203                         AssertEquals ("ExcludeClip1", 3, rects.Length);
204
205                         AssertEquals ("ExcludeClip2", 10, rects[0].X);
206                         AssertEquals ("ExcludeClip3", 10, rects[0].Y);
207                         AssertEquals ("ExcludeClip4", 100, rects[0].Width);
208                         AssertEquals ("ExcludeClip5", 50, rects[0].Height);
209
210                         AssertEquals ("ExcludeClip6", 10, rects[1].X);
211                         AssertEquals ("ExcludeClip7", 60, rects[1].Y);
212                         AssertEquals ("ExcludeClip8", 30, rects[1].Width);
213                         AssertEquals ("ExcludeClip9", 20, rects[1].Height);
214
215                         AssertEquals ("ExcludeClip10", 10, rects[2].X);
216                         AssertEquals ("ExcludeClip11", 80, rects[2].Y);
217                         AssertEquals ("ExcludeClip12", 100, rects[2].Width);
218                         AssertEquals ("ExcludeClip13", 30, rects[2].Height);
219                 }
220
221                 [Test]
222                 public void IntersectClip ()
223                 {
224                         Bitmap bmp = new Bitmap (200, 200);
225                         Graphics g = Graphics.FromImage (bmp);
226
227                         g.Clip = new Region (new RectangleF (260, 30, 60, 80));
228                         g.IntersectClip (new Rectangle (290, 40, 60, 80));
229                         rects = g.Clip.GetRegionScans (new Matrix ());
230
231                         AssertEquals ("IntersectClip", 1, rects.Length);
232
233                         AssertEquals ("IntersectClip", 290, rects[0].X);
234                         AssertEquals ("IntersectClip", 40, rects[0].Y);
235                         AssertEquals ("IntersectClip", 30, rects[0].Width);
236                         AssertEquals ("IntersectClip", 70, rects[0].Height);
237                 }
238
239                 [Test]
240                 public void ResetClip ()
241                 {
242                         Bitmap bmp = new Bitmap (200, 200);
243                         Graphics g = Graphics.FromImage (bmp);
244
245                         g.Clip = new Region (new RectangleF (260, 30, 60, 80));
246                         g.IntersectClip (new Rectangle (290, 40, 60, 80));
247                         g.ResetClip ();
248                         rects = g.Clip.GetRegionScans (new Matrix ());
249
250                         AssertEquals ("ResetClip", 1, rects.Length);
251
252                         AssertEquals ("ResetClip", -4194304, rects[0].X);
253                         AssertEquals ("ResetClip", -4194304, rects[0].Y);
254                         AssertEquals ("ResetClip", 8388608, rects[0].Width);
255                         AssertEquals ("ResetClip", 8388608, rects[0].Height);
256                 }
257
258                 [Test]
259                 public void SetClip ()
260                 {
261                         RectangleF[] rects ;
262                         Bitmap bmp = new Bitmap (200, 200);
263                         Graphics g = Graphics.FromImage (bmp);
264
265                         // Region
266                         g.SetClip (new Region (new Rectangle (50, 40, 210, 220)), CombineMode.Replace);
267                         rects = g.Clip.GetRegionScans (new Matrix ());
268                         AssertEquals ("SetClip1", 1, rects.Length);
269                         AssertEquals ("SetClip2", 50, rects[0].X);
270                         AssertEquals ("SetClip3", 40, rects[0].Y);
271                         AssertEquals ("SetClip4", 210, rects[0].Width);
272                         AssertEquals ("SetClip5", 220, rects[0].Height);
273
274                         // RectangleF
275                         g = Graphics.FromImage (bmp);
276                         g.SetClip (new RectangleF (50, 40, 210, 220));
277                         rects = g.Clip.GetRegionScans (new Matrix ());
278                         AssertEquals ("SetClip6", 1, rects.Length);
279                         AssertEquals ("SetClip7", 50, rects[0].X);
280                         AssertEquals ("SetClip8", 40, rects[0].Y);
281                         AssertEquals ("SetClip9", 210, rects[0].Width);
282                         AssertEquals ("SetClip10", 220, rects[0].Height);
283
284                         // Rectangle
285                         g = Graphics.FromImage (bmp);
286                         g.SetClip (new Rectangle (50, 40, 210, 220));
287                         rects = g.Clip.GetRegionScans (new Matrix ());
288                         AssertEquals ("SetClip10", 1, rects.Length);
289                         AssertEquals ("SetClip11", 50, rects[0].X);
290                         AssertEquals ("SetClip12", 40, rects[0].Y);
291                         AssertEquals ("SetClip13", 210, rects[0].Width);
292                         AssertEquals ("SetClip14", 220, rects[0].Height);
293                 }
294                 
295                 [Test]
296                 public void SetSaveReset ()
297                 {
298                         Bitmap bmp = new Bitmap (200, 200);
299                         Graphics g = Graphics.FromImage (bmp);
300                         GraphicsState state_default, state_modified;
301                         
302                         state_default = g.Save (); // Default
303                         
304                         g.CompositingMode = CompositingMode.SourceCopy;
305                         g.CompositingQuality = CompositingQuality.GammaCorrected;
306                         g.InterpolationMode = InterpolationMode.HighQualityBilinear;
307                         g.PageScale = 2;
308                         g.PageUnit = GraphicsUnit.Inch;                 
309                         g.PixelOffsetMode = PixelOffsetMode.Half;
310                         g.Clip = new Region (new Rectangle (0, 0, 100, 100));
311                         g.RenderingOrigin = new Point (10, 20);
312                         g.SmoothingMode = SmoothingMode.AntiAlias;
313                         g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
314                         
315                         
316                         state_modified = g.Save (); // Modified
317                         
318                         g.CompositingMode = CompositingMode.SourceOver;
319                         g.CompositingQuality = CompositingQuality.Default;
320                         g.InterpolationMode = InterpolationMode.Bilinear;
321                         g.PageScale = 5;
322                         g.PageUnit = GraphicsUnit.Display;                      
323                         g.PixelOffsetMode = PixelOffsetMode.Default;
324                         g.Clip = new Region (new Rectangle (1, 2, 20, 25));
325                         g.RenderingOrigin = new Point (5, 6);
326                         g.SmoothingMode = SmoothingMode.None;
327                         g.TextRenderingHint = TextRenderingHint.SystemDefault;                  
328                                                 
329                         g.Restore (state_modified);
330                         
331                         AssertEquals ("SetSaveReset1", CompositingMode.SourceCopy, g.CompositingMode);
332                         AssertEquals ("SetSaveReset2", CompositingQuality.GammaCorrected, g.CompositingQuality);
333                         AssertEquals ("SetSaveReset3", InterpolationMode.HighQualityBilinear, g.InterpolationMode);
334                         AssertEquals ("SetSaveReset4", 2, g.PageScale);
335                         AssertEquals ("SetSaveReset5", GraphicsUnit.Inch, g.PageUnit);
336                         AssertEquals ("SetSaveReset6", PixelOffsetMode.Half, g.PixelOffsetMode);
337                         AssertEquals ("SetSaveReset7", new Point (10, 20), g.RenderingOrigin);
338                         AssertEquals ("SetSaveReset8", SmoothingMode.AntiAlias, g.SmoothingMode);
339                         AssertEquals ("SetSaveReset9", TextRenderingHint.ClearTypeGridFit, g.TextRenderingHint);                        
340                         AssertEquals ("SetSaveReset10", 0, (int) g.ClipBounds.X);
341                         AssertEquals ("SetSaveReset10", 0, (int) g.ClipBounds.Y);
342                         
343                         g.Restore (state_default);                      
344                         
345                         AssertEquals ("SetSaveReset11", CompositingMode.SourceOver, g.CompositingMode);
346                         AssertEquals ("SetSaveReset12", CompositingQuality.Default, g.CompositingQuality);
347                         AssertEquals ("SetSaveReset13", InterpolationMode.Bilinear, g.InterpolationMode);
348                         AssertEquals ("SetSaveReset14", 1, g.PageScale);
349                         AssertEquals ("SetSaveReset15", GraphicsUnit.Display, g.PageUnit);
350                         AssertEquals ("SetSaveReset16", PixelOffsetMode.Default, g.PixelOffsetMode);
351                         AssertEquals ("SetSaveReset17", new Point (0, 0) , g.RenderingOrigin);
352                         AssertEquals ("SetSaveReset18", SmoothingMode.None, g.SmoothingMode);
353                         AssertEquals ("SetSaveReset19", TextRenderingHint.SystemDefault, g.TextRenderingHint);          
354
355                         Region r = new Region ();
356                         AssertEquals ("SetSaveReset20", r.GetBounds (g) , g.ClipBounds);
357                         
358                         g.Dispose ();                   
359                 }
360
361                 [Test]
362                 public void LoadIndexed ()
363                 {
364                         //
365                         // Tests that we can load an indexed file
366                         //
367
368                         Stream str = Assembly.GetExecutingAssembly ().GetManifestResourceStream ("indexed.png");
369                         Image x = Image.FromStream (str);
370                         Graphics g = Graphics.FromImage (x);
371                 }
372                 
373                 [Test]
374                 [ExpectedException (typeof (ArgumentNullException))]
375                 public void FromImage ()
376                 {
377                         Graphics g = Graphics.FromImage (null);
378                 }
379
380                 private Graphics Get (int w, int h)
381                 {
382                         Bitmap bitmap = new Bitmap (w, h);
383                         Graphics g = Graphics.FromImage (bitmap);
384                         g.Clip = new Region (new Rectangle (0, 0, w, h));
385                         return g;
386                 }
387
388                 private void Compare (string msg, RectangleF b1, RectangleF b2)
389                 {
390                         AssertEquals (msg + ".compare.X", b1.X, b2.X);
391                         AssertEquals (msg + ".compare.Y", b1.Y, b2.Y);
392                         AssertEquals (msg + ".compare.Width", b1.Width, b2.Width);
393                         AssertEquals (msg + ".compare.Height", b1.Height, b2.Height);
394                 }
395
396                 [Test]
397                 public void Clip_GetBounds ()
398                 {
399                         Graphics g = Get (16, 16);
400                         RectangleF bounds = g.Clip.GetBounds (g);
401                         AssertEquals ("X", 0, bounds.X);
402                         AssertEquals ("Y", 0, bounds.Y);
403                         AssertEquals ("Width", 16, bounds.Width);
404                         AssertEquals ("Height", 16, bounds.Height);
405                         Assert.IsTrue (g.Transform.IsIdentity, "Identity");
406                         g.Dispose ();
407                 }
408
409                 [Test]
410                 public void Clip_TranslateTransform ()
411                 {
412                         Graphics g = Get (16, 16);
413                         g.TranslateTransform (12.22f, 10.10f);
414                         RectangleF bounds = g.Clip.GetBounds (g);
415                         Compare ("translate", bounds, g.ClipBounds);
416                         AssertEquals ("translate.X", -12.22, bounds.X);
417                         AssertEquals ("translate.Y", -10.10, bounds.Y);
418                         AssertEquals ("translate.Width", 16, bounds.Width);
419                         AssertEquals ("translate.Height", 16, bounds.Height);
420                         float[] elements = g.Transform.Elements;
421                         AssertEquals ("translate.0", 1, elements[0]);
422                         AssertEquals ("translate.1", 0, elements[1]);
423                         AssertEquals ("translate.2", 0, elements[2]);
424                         AssertEquals ("translate.3", 1, elements[3]);
425                         AssertEquals ("translate.4", 12.22, elements[4]);
426                         AssertEquals ("translate.5", 10.10, elements[5]);
427
428                         g.ResetTransform ();
429                         bounds = g.Clip.GetBounds (g);
430                         Compare ("reset", bounds, g.ClipBounds);
431                         AssertEquals ("reset.X", 0, bounds.X);
432                         AssertEquals ("reset.Y", 0, bounds.Y);
433                         AssertEquals ("reset.Width", 16, bounds.Width);
434                         AssertEquals ("reset.Height", 16, bounds.Height);
435                         Assert.IsTrue (g.Transform.IsIdentity, "Identity");
436                         g.Dispose ();
437                 }
438
439                 [Test]
440                 [ExpectedException (typeof (ArgumentException))]
441                 public void Transform_NonInvertibleMatrix ()
442                 {
443                         Matrix matrix = new Matrix (123, 24, 82, 16, 47, 30);
444                         Assert.IsFalse (matrix.IsInvertible, "IsInvertible");
445                         Graphics g = Get (16, 16);
446                         g.Transform = matrix;
447                 }
448
449
450                 [Test]
451                 [ExpectedException (typeof (ArgumentException))]
452                 public void Multiply_NonInvertibleMatrix ()
453                 {
454                         Matrix matrix = new Matrix (123, 24, 82, 16, 47, 30);
455                         Assert.IsFalse (matrix.IsInvertible, "IsInvertible");
456                         Graphics g = Get (16, 16);
457                         g.MultiplyTransform (matrix);
458                 }
459
460                 private void CheckBounds (string msg, RectangleF bounds, float x, float y, float w, float h)
461                 {
462                         AssertEquals (msg + ".X", x, bounds.X, 0.1);
463                         AssertEquals (msg + ".Y", y, bounds.Y, 0.1);
464                         AssertEquals (msg + ".Width", w, bounds.Width, 0.1);
465                         AssertEquals (msg + ".Height", h, bounds.Height, 0.1);
466                 }
467
468                 [Test]
469                 public void ClipBounds ()
470                 {
471                         Graphics g = Get (16, 16);
472                         CheckBounds ("graphics.ClipBounds", g.ClipBounds, 0, 0, 16, 16);
473                         CheckBounds ("graphics.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 16, 16);
474
475                         g.Clip = new Region (new Rectangle (0, 0, 8, 8));
476                         CheckBounds ("clip.ClipBounds", g.ClipBounds, 0, 0, 8, 8);
477                         CheckBounds ("clip.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 8, 8);
478                 }
479
480                 [Test]
481                 public void ClipBounds_Rotate ()
482                 {
483                         Graphics g = Get (16, 16);
484                         g.Clip = new Region (new Rectangle (0, 0, 8, 8));
485                         g.RotateTransform (90);
486                         CheckBounds ("rotate.ClipBounds", g.ClipBounds, 0, -8, 8, 8);
487                         CheckBounds ("rotate.Clip.GetBounds", g.Clip.GetBounds (g), 0, -8, 8, 8);
488
489                         g.Transform = new Matrix ();
490                         CheckBounds ("identity.ClipBounds", g.Clip.GetBounds (g), 0, 0, 8, 8);
491                         CheckBounds ("identity.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 8, 8);
492                 }
493
494                 [Test]
495                 public void ClipBounds_Scale ()
496                 {
497                         RectangleF clip = new Rectangle (0, 0, 8, 8);
498                         Graphics g = Get (16, 16);
499                         g.Clip = new Region (clip);
500                         g.ScaleTransform (0.25f, 0.5f);
501                         CheckBounds ("scale.ClipBounds", g.ClipBounds, 0, 0, 32, 16);
502                         CheckBounds ("scale.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 32, 16);
503
504                         g.SetClip (clip);
505                         CheckBounds ("setclip.ClipBounds", g.ClipBounds, 0, 0, 8, 8);
506                         CheckBounds ("setclip.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 8, 8);
507                 }
508
509                 [Test]
510                 public void ClipBounds_Translate ()
511                 {
512                         Graphics g = Get (16, 16);
513                         g.Clip = new Region (new Rectangle (0, 0, 8, 8));
514                         Region clone = g.Clip.Clone ();
515                         g.TranslateTransform (8, 8);
516                         CheckBounds ("translate.ClipBounds", g.ClipBounds, -8, -8, 8, 8);
517                         CheckBounds ("translate.Clip.GetBounds", g.Clip.GetBounds (g), -8, -8, 8, 8);
518
519                         g.SetClip (clone, CombineMode.Replace);
520                         CheckBounds ("setclip.ClipBounds", g.Clip.GetBounds (g), 0, 0, 8, 8);
521                         CheckBounds ("setclip.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 8, 8);
522                 }
523
524                 [Test]
525                 public void ClipBounds_Transform_Translation ()
526                 {
527                         Graphics g = Get (16, 16);
528                         g.Clip = new Region (new Rectangle (0, 0, 8, 8));
529                         g.Transform = new Matrix (1, 0, 0, 1, 8, 8);
530                         CheckBounds ("transform.ClipBounds", g.ClipBounds, -8, -8, 8, 8);
531                         CheckBounds ("transform.Clip.GetBounds", g.Clip.GetBounds (g), -8, -8, 8, 8);
532
533                         g.ResetTransform ();
534                         CheckBounds ("reset.ClipBounds", g.ClipBounds, 0, 0, 8, 8);
535                         CheckBounds ("reset.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 8, 8);
536                 }
537
538                 [Test]
539                 public void ClipBounds_Transform_Scale ()
540                 {
541                         Graphics g = Get (16, 16);
542                         g.Clip = new Region (new Rectangle (0, 0, 8, 8));
543                         g.Transform = new Matrix (0.5f, 0, 0, 0.25f, 0, 0);
544                         CheckBounds ("scale.ClipBounds", g.ClipBounds, 0, 0, 16, 32);
545                         CheckBounds ("scale.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 16, 32);
546
547                         g.ResetClip ();
548                         // see next test for ClipBounds
549                         CheckBounds ("resetclip.Clip.GetBounds", g.Clip.GetBounds (g), -4194304, -4194304, 8388608, 8388608);
550                         Assert.IsTrue (g.Clip.IsInfinite (g), "IsInfinite");
551                 }
552
553                 [Test]
554                 [Category ("NotWorking")]
555                 public void ClipBounds_Transform_Scale_Strange ()
556                 {
557                         Graphics g = Get (16, 16);
558                         g.Clip = new Region (new Rectangle (0, 0, 8, 8));
559                         g.Transform = new Matrix (0.5f, 0, 0, 0.25f, 0, 0);
560                         CheckBounds ("scale.ClipBounds", g.ClipBounds, 0, 0, 16, 32);
561                         CheckBounds ("scale.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 16, 32);
562
563                         g.ResetClip ();
564                         // note: strange case where g.ClipBounds and g.Clip.GetBounds are different
565                         CheckBounds ("resetclip.ClipBounds", g.ClipBounds, -8388608, -16777216, 16777216, 33554432);
566                 }
567
568                 [Test]
569                 public void ClipBounds_Multiply ()
570                 {
571                         Graphics g = Get (16, 16);
572                         g.Clip = new Region (new Rectangle (0, 0, 8, 8));
573                         g.Transform = new Matrix (1, 0, 0, 1, 8, 8);
574                         g.MultiplyTransform (g.Transform);
575                         CheckBounds ("multiply.ClipBounds", g.ClipBounds, -16, -16, 8, 8);
576                         CheckBounds ("multiply.Clip.GetBounds", g.Clip.GetBounds (g), -16, -16, 8, 8);
577
578                         g.ResetTransform ();
579                         CheckBounds ("reset.ClipBounds", g.ClipBounds, 0, 0, 8, 8);
580                         CheckBounds ("reset.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 8, 8);
581                 }
582
583                 [Test]
584                 public void ClipBounds_Cumulative_Effects ()
585                 {
586                         Graphics g = Get (16, 16);
587                         CheckBounds ("graphics.ClipBounds", g.ClipBounds, 0, 0, 16, 16);
588                         CheckBounds ("graphics.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 16, 16);
589
590                         g.Clip = new Region (new Rectangle (0, 0, 8, 8));
591                         CheckBounds ("clip.ClipBounds", g.ClipBounds, 0, 0, 8, 8);
592                         CheckBounds ("clip.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 8, 8);
593
594                         g.RotateTransform (90);
595                         CheckBounds ("rotate.ClipBounds", g.ClipBounds, 0, -8, 8, 8);
596                         CheckBounds ("rotate.Clip.GetBounds", g.Clip.GetBounds (g), 0, -8, 8, 8);
597
598                         g.ScaleTransform (0.25f, 0.5f);
599                         CheckBounds ("scale.ClipBounds", g.ClipBounds, 0, -16, 32, 16);
600                         CheckBounds ("scale.Clip.GetBounds", g.Clip.GetBounds (g), 0, -16, 32, 16);
601
602                         g.TranslateTransform (8, 8);
603                         CheckBounds ("translate.ClipBounds", g.ClipBounds, -8, -24, 32, 16);
604                         CheckBounds ("translate.Clip.GetBounds", g.Clip.GetBounds (g), -8, -24, 32, 16);
605                         
606                         g.MultiplyTransform (g.Transform);
607                         CheckBounds ("multiply.ClipBounds", g.ClipBounds, -104, -56, 64, 64);
608                         CheckBounds ("multiply.Clip.GetBounds", g.Clip.GetBounds (g), -104, -56, 64, 64);
609
610                         g.ResetTransform ();
611                         CheckBounds ("reset.ClipBounds", g.ClipBounds, 0, 0, 8, 8);
612                         CheckBounds ("reset.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 8, 8);
613                 }
614
615                 [Test]
616                 public void Clip_TranslateTransform_BoundsChange ()
617                 {
618                         Graphics g = Get (16, 16);
619                         CheckBounds ("graphics.ClipBounds", g.ClipBounds, 0, 0, 16, 16);
620                         CheckBounds ("graphics.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 16, 16);
621                         g.TranslateTransform (-16, -16);
622                         CheckBounds ("translated.ClipBounds", g.ClipBounds, 16, 16, 16, 16);
623                         CheckBounds ("translated.Clip.GetBounds", g.Clip.GetBounds (g), 16, 16, 16, 16);
624
625                         g.Clip = new Region (new Rectangle (0, 0, 8, 8));
626                         // ClipBounds isn't affected by a previous translation
627                         CheckBounds ("rectangle.ClipBounds", g.ClipBounds, 0, 0, 8, 8);
628                         // Clip.GetBounds isn't affected by a previous translation
629                         CheckBounds ("rectangle.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 8, 8);
630
631                         g.ResetTransform ();
632                         CheckBounds ("reseted.ClipBounds", g.ClipBounds, -16, -16, 8, 8);
633                         CheckBounds ("reseted.Clip.GetBounds", g.Clip.GetBounds (g), -16, -16, 8, 8);
634                 }
635
636                 [Test]
637                 public void Clip_RotateTransform_BoundsChange ()
638                 {
639                         Graphics g = Get (16, 16);
640                         CheckBounds ("graphics.ClipBounds", g.ClipBounds, 0, 0, 16, 16);
641                         CheckBounds ("graphics.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 16, 16);
642                         // we select a "simple" angle because the region will be converted into
643                         // a bitmap (well for libgdiplus) and we would lose precision after that
644                         g.RotateTransform (90);
645                         CheckBounds ("rotated.ClipBounds", g.ClipBounds, 0, -16, 16, 16);
646                         CheckBounds ("rotated.Clip.GetBounds", g.Clip.GetBounds (g), 0, -16, 16, 16);
647                         g.Clip = new Region (new Rectangle (0, 0, 8, 8));
648                         // ClipBounds isn't affected by a previous rotation (90)
649                         CheckBounds ("rectangle.ClipBounds", g.ClipBounds, 0, 0, 8, 8);
650                         // Clip.GetBounds isn't affected by a previous rotation
651                         CheckBounds ("rectangle.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 8, 8);
652
653                         g.ResetTransform ();
654                         CheckBounds ("reseted.ClipBounds", g.ClipBounds, -8, 0, 8, 8);
655                         CheckBounds ("reseted.Clip.GetBounds", g.Clip.GetBounds (g), -8, 0, 8, 8);
656                 }
657
658                 private void CheckBoundsInt (string msg, RectangleF bounds, int x, int y, int w, int h)
659                 {
660                         // currently bounds are rounded at 8 pixels (FIXME - we can go down to 1 pixel)
661                         AssertEquals (msg + ".X", x, bounds.X, 4f);
662                         AssertEquals (msg + ".Y", y, bounds.Y, 4f);
663                         AssertEquals (msg + ".Width", w, bounds.Width, 4f);
664                         AssertEquals (msg + ".Height", h, bounds.Height, 4f);
665                 }
666
667                 [Test]
668                 [Category ("NotWorking")]
669                 public void Clip_RotateTransform_BoundsChange_45 ()
670                 {
671                         Graphics g = Get (16, 16);
672                         CheckBounds ("graphics.ClipBounds", g.ClipBounds, 0, 0, 16, 16);
673                         CheckBounds ("graphics.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 16, 16);
674                         g.RotateTransform (45);
675                         // we can't use the "normal" CheckBound here because of libgdiplus crude rounding
676                         CheckBoundsInt ("rotated.ClipBounds", g.ClipBounds, 0, -11, 24, 24);
677                         CheckBoundsInt ("rotated.Clip.GetBounds", g.Clip.GetBounds (g), 0, -11, 24, 24);
678                         g.Clip = new Region (new Rectangle (0, 0, 8, 8));
679                         // ClipBounds IS affected by a previous rotation (45)
680                         CheckBoundsInt ("rectangle.ClipBounds", g.ClipBounds, -3, -4, 16, 16);
681                         // Clip.GetBounds isn't affected by a previous rotation
682                         CheckBounds ("rectangle.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 8, 8);
683
684                         g.ResetTransform ();
685                         CheckBounds ("reseted.ClipBounds", g.ClipBounds, -5, 1, 11, 11);
686                         CheckBounds ("reseted.Clip.GetBounds", g.Clip.GetBounds (g), -5.6f, 0, 11.3f, 11.3f);
687                 }
688
689                 [Test]
690                 public void Clip_ScaleTransform_NoBoundsChange ()
691                 {
692                         Graphics g = Get (16, 16);
693                         CheckBounds ("graphics.ClipBounds", g.ClipBounds, 0, 0, 16, 16);
694                         CheckBounds ("graphics.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 16, 16);
695                         g.ScaleTransform (2, 0.5f);
696                         CheckBounds ("scaled.ClipBounds", g.ClipBounds, 0, 0, 8, 32);
697                         CheckBounds ("scaled.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 8, 32);
698                         g.Clip = new Region (new Rectangle (0, 0, 8, 8));
699                         // ClipBounds isn't affected by a previous scaling
700                         CheckBounds ("rectangle.ClipBounds", g.ClipBounds, 0, 0, 8, 8);
701                         // Clip.GetBounds isn't affected by a previous scaling
702                         CheckBounds ("rectangle.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 8, 8);
703
704                         g.ResetTransform ();
705                         CheckBounds ("reseted.ClipBounds", g.ClipBounds, 0, 0, 16, 4);
706                         CheckBounds ("reseted.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 16, 4);
707                 }
708
709                 [Test]
710                 [Category ("NotWorking")]
711                 public void Clip_MultiplyTransform_NoBoundsChange ()
712                 {
713                         Graphics g = Get (16, 16);
714                         CheckBounds ("graphics.ClipBounds", g.ClipBounds, 0, 0, 16, 16);
715                         CheckBounds ("graphics.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 16, 16);
716                         g.MultiplyTransform (new Matrix (2.5f, 0.5f, -2.5f, 0.5f, 4, -4));
717                         CheckBounds ("multiplied.ClipBounds", g.ClipBounds, 3.2f, 1.6f, 19.2f, 19.2f);
718                         CheckBounds ("multiplied.Clip.GetBounds", g.Clip.GetBounds (g), 3.2f, 1.6f, 19.2f, 19.2f);
719                         g.Clip = new Region (new Rectangle (0, 0, 8, 8));
720                         // ClipBounds IS affected by the previous multiplication
721                         CheckBounds ("rectangle.ClipBounds", g.ClipBounds, -3, -3, 15, 15);
722                         // Clip.GetBounds isn't affected by the previous multiplication
723                         CheckBounds ("rectangle.Clip.GetBounds", g.Clip.GetBounds (g), 0, 0, 8, 8);
724
725                         g.ResetTransform ();
726                         CheckBounds ("reseted.ClipBounds", g.ClipBounds, -16, -3, 40, 7);
727                         CheckBounds ("reseted.Clip.GetBounds", g.Clip.GetBounds (g), -16, -4, 40, 8);
728                 }
729
730                 [Test]
731                 [ExpectedException (typeof (ArgumentException))]
732                 public void ScaleTransform_X0 ()
733                 {
734                         Graphics g = Get (16, 16);
735                         g.ScaleTransform (0, 1);
736                 }
737
738                 [Test]
739                 [ExpectedException (typeof (ArgumentException))]
740                 public void ScaleTransform_Y0 ()
741                 {
742                         Graphics g = Get (16, 16);
743                         g.ScaleTransform (1, 0);
744                 }
745
746                 [Test]
747                 public void TranslateTransform_Order ()
748                 {
749                         Graphics g = Get (16, 16);
750                         g.Transform = new Matrix (1, 2, 3, 4, 5, 6);
751                         g.TranslateTransform (3, -3);
752                         float[] elements = g.Transform.Elements;
753                         AssertEquals ("default.0", 1, elements[0]);
754                         AssertEquals ("default.1", 2, elements[1]);
755                         AssertEquals ("default.2", 3, elements[2]);
756                         AssertEquals ("default.3", 4, elements[3]);
757                         AssertEquals ("default.4", -1, elements[4]);
758                         AssertEquals ("default.5", 0, elements[5]);
759
760                         g.Transform = new Matrix (1, 2, 3, 4, 5, 6);
761                         g.TranslateTransform (3, -3, MatrixOrder.Prepend);
762                         elements = g.Transform.Elements;
763                         AssertEquals ("prepend.0", 1, elements[0]);
764                         AssertEquals ("prepend.1", 2, elements[1]);
765                         AssertEquals ("prepend.2", 3, elements[2]);
766                         AssertEquals ("prepend.3", 4, elements[3]);
767                         AssertEquals ("prepend.4", -1, elements[4]);
768                         AssertEquals ("prepend.5", 0, elements[5]);
769
770                         g.Transform = new Matrix (1, 2, 3, 4, 5, 6);
771                         g.TranslateTransform (3, -3, MatrixOrder.Append);
772                         elements = g.Transform.Elements;
773                         AssertEquals ("append.0", 1, elements[0]);
774                         AssertEquals ("append.1", 2, elements[1]);
775                         AssertEquals ("append.2", 3, elements[2]);
776                         AssertEquals ("append.3", 4, elements[3]);
777                         AssertEquals ("append.4", 8, elements[4]);
778                         AssertEquals ("append.5", 3, elements[5]);
779                 }
780
781                 static Point[] SmallCurve = new Point[3] { new Point (0, 0), new Point (15, 5), new Point (5, 15) };
782                 static PointF[] SmallCurveF = new PointF[3] { new PointF (0, 0), new PointF (15, 5), new PointF (5, 15) };
783
784                 static Point[] TooSmallCurve = new Point[2] { new Point (0, 0), new Point (15, 5) };
785                 static PointF[] LargeCurveF = new PointF[4] { new PointF (0, 0), new PointF (15, 5), new PointF (5, 15), new PointF (0, 20) };
786
787                 [Test]
788                 [ExpectedException (typeof (ArgumentNullException))]
789                 public void DrawCurve_PenNull ()
790                 {
791                         Bitmap bitmap = new Bitmap (20, 20);
792                         Graphics g = Graphics.FromImage (bitmap);
793                         g.DrawCurve (null, SmallCurveF);
794                 }
795
796                 [Test]
797                 [ExpectedException (typeof (ArgumentNullException))]
798                 public void DrawCurve_PointFNull ()
799                 {
800                         Bitmap bitmap = new Bitmap (20, 20);
801                         Graphics g = Graphics.FromImage (bitmap);
802                         g.DrawCurve (Pens.Black, (PointF[]) null);
803                 }
804
805                 [Test]
806                 [ExpectedException (typeof (ArgumentNullException))]
807                 public void DrawCurve_PointNull ()
808                 {
809                         Bitmap bitmap = new Bitmap (20, 20);
810                         Graphics g = Graphics.FromImage (bitmap);
811                         g.DrawCurve (Pens.Black, (Point[]) null);
812                 }
813
814                 [Test]
815                 public void DrawCurve_NotEnoughPoints ()
816                 {
817                         Bitmap bitmap = new Bitmap (20, 20);
818                         Graphics g = Graphics.FromImage (bitmap);
819                         CheckForEmptyBitmap (bitmap);
820                         g.DrawCurve (Pens.Black, TooSmallCurve, 0.5f);
821                         CheckForNonEmptyBitmap (bitmap);
822                         // so a "curve" can be drawn with less than 3 points!
823                         // actually I used to call that a line... (and it's not related to tension)
824                         g.Dispose ();
825                         bitmap.Dispose ();
826                 }
827
828                 [Test]
829                 [ExpectedException (typeof (ArgumentException))]
830                 public void DrawCurve_SinglePoint ()
831                 {
832                         Bitmap bitmap = new Bitmap (20, 20);
833                         Graphics g = Graphics.FromImage (bitmap);
834                         g.DrawCurve (Pens.Black, new Point[1] { new Point (10, 10) }, 0.5f);
835                         // a single point isn't enough
836                 }
837
838                 [Test]
839                 [ExpectedException (typeof (ArgumentException))]
840                 public void DrawCurve3_NotEnoughPoints ()
841                 {
842                         Bitmap bitmap = new Bitmap (20, 20);
843                         Graphics g = Graphics.FromImage (bitmap);
844                         g.DrawCurve (Pens.Black, TooSmallCurve, 0, 2, 0.5f);
845                         // aha, this is API dependent
846                 }
847
848                 [Test]
849                 public void DrawCurve_NegativeTension ()
850                 {
851                         Bitmap bitmap = new Bitmap (20, 20);
852                         Graphics g = Graphics.FromImage (bitmap);
853                         // documented as bigger (or equals) to 0
854                         g.DrawCurve (Pens.Black, SmallCurveF, -0.9f);
855                         CheckForNonEmptyBitmap (bitmap);
856                         g.Dispose ();
857                         bitmap.Dispose ();
858                 }
859
860                 [Test]
861                 public void DrawCurve_PositiveTension ()
862                 {
863                         Bitmap bitmap = new Bitmap (20, 20);
864                         Graphics g = Graphics.FromImage (bitmap);
865                         g.DrawCurve (Pens.Black, SmallCurveF, 0.9f);
866                         // this is not the same as -1
867                         CheckForNonEmptyBitmap (bitmap);
868                         g.Dispose ();
869                         bitmap.Dispose ();
870                 }
871
872                 [Test]
873                 [Category ("NotWorking")] // libgdiplus is drawing something
874                 public void DrawCurve_LargeTension ()
875                 {
876                         Bitmap bitmap = new Bitmap (20, 20);
877                         Graphics g = Graphics.FromImage (bitmap);
878                         g.DrawCurve (Pens.Black, SmallCurve, Single.MaxValue);
879                         CheckForEmptyBitmap (bitmap);
880                         // too much tension ;)
881                         g.Dispose ();
882                         bitmap.Dispose ();
883                 }
884
885                 [Test]
886                 [ExpectedException (typeof (ArgumentException))]
887                 public void DrawCurve_ZeroSegments ()
888                 {
889                         Bitmap bitmap = new Bitmap (20, 20);
890                         Graphics g = Graphics.FromImage (bitmap);
891                         g.DrawCurve (Pens.Black, SmallCurveF, 0, 0);
892                 }
893
894                 [Test]
895                 [ExpectedException (typeof (ArgumentException))]
896                 public void DrawCurve_NegativeSegments ()
897                 {
898                         Bitmap bitmap = new Bitmap (20, 20);
899                         Graphics g = Graphics.FromImage (bitmap);
900                         g.DrawCurve (Pens.Black, SmallCurveF, 0, -1);
901                 }
902
903                 [Test]
904                 [ExpectedException (typeof (ArgumentException))]
905                 public void DrawCurve_OffsetTooLarge ()
906                 {
907                         Bitmap bitmap = new Bitmap (20, 20);
908                         Graphics g = Graphics.FromImage (bitmap);
909                         // starting offset 1 doesn't give 3 points to make a curve
910                         g.DrawCurve (Pens.Black, SmallCurveF, 1, 2);
911                         // and in this case 2 points aren't enough to draw something
912                 }
913
914                 [Test]
915                 public void DrawCurve_Offset_0 ()
916                 {
917                         Bitmap bitmap = new Bitmap (20, 20);
918                         Graphics g = Graphics.FromImage (bitmap);
919                         g.DrawCurve (Pens.Black, LargeCurveF, 0, 2, 0.5f);
920                         CheckForNonEmptyBitmap (bitmap);
921                         g.Dispose ();
922                         bitmap.Dispose ();
923                 }
924
925                 [Test]
926                 public void DrawCurve_Offset_1 ()
927                 {
928                         Bitmap bitmap = new Bitmap (20, 20);
929                         Graphics g = Graphics.FromImage (bitmap);
930                         g.DrawCurve (Pens.Black, LargeCurveF, 1, 2, 0.5f);
931                         CheckForNonEmptyBitmap (bitmap);
932                         g.Dispose ();
933                         bitmap.Dispose ();
934                 }
935
936                 [Test]
937                 public void DrawCurve_Offset_2 ()
938                 {
939                         Bitmap bitmap = new Bitmap (20, 20);
940                         Graphics g = Graphics.FromImage (bitmap);
941                         // it works even with two points because we know the previous ones
942                         g.DrawCurve (Pens.Black, LargeCurveF, 2, 1, 0.5f);
943                         CheckForNonEmptyBitmap (bitmap);
944                         g.Dispose ();
945                         bitmap.Dispose ();
946                 }
947
948                 [Test]
949                 public void DrawRectangle_Negative ()
950                 {
951                         Bitmap bitmap = new Bitmap (20, 20);
952                         Graphics g = Graphics.FromImage (bitmap);
953                         Pen pen = new Pen (Color.Red);
954                         g.DrawRectangle (pen, 5, 5, -10, -10);
955                         g.DrawRectangle (pen, 0.0f, 0.0f, 5.0f, -10.0f);
956                         g.DrawRectangle (pen, new Rectangle (15, 0, -10, 5));
957                         CheckForEmptyBitmap (bitmap);
958                         pen.Dispose ();
959                         g.Dispose ();
960                         bitmap.Dispose ();
961                 }
962
963                 [Test]
964                 public void DrawRectangles_Negative ()
965                 {
966                         Bitmap bitmap = new Bitmap (20, 20);
967                         Graphics g = Graphics.FromImage (bitmap);
968                         Pen pen = new Pen (Color.Red);
969                         Rectangle[] rects = new Rectangle[2] {
970                                 new Rectangle (5, 5, -10, -10), new Rectangle (0, 0, 5, -10)
971                         };
972                         RectangleF[] rectf = new RectangleF[2] {
973                                 new RectangleF (0.0f, 5.0f, -10.0f, -10.0f), new RectangleF (15.0f, 0.0f, -10.0f, 5.0f)
974                         };
975                         g.DrawRectangles (pen, rects);
976                         g.DrawRectangles (pen, rectf);
977                         CheckForEmptyBitmap (bitmap);
978                         pen.Dispose ();
979                         g.Dispose ();
980                         bitmap.Dispose ();
981                 }
982
983                 [Test]
984                 public void FillRectangle_Negative ()
985                 {
986                         Bitmap bitmap = new Bitmap (20, 20);
987                         Graphics g = Graphics.FromImage (bitmap);
988                         SolidBrush brush = new SolidBrush (Color.Red);
989                         g.FillRectangle (brush, 5, 5, -10, -10);
990                         g.FillRectangle (brush, 0.0f, 0.0f, 5.0f, -10.0f);
991                         g.FillRectangle (brush, new Rectangle (15, 0, -10, 5));
992                         CheckForEmptyBitmap (bitmap);
993                         brush.Dispose ();
994                         g.Dispose ();
995                         bitmap.Dispose ();
996                 }
997
998                 [Test]
999                 public void FillRectangles_Negative ()
1000                 {
1001                         Bitmap bitmap = new Bitmap (20, 20);
1002                         Graphics g = Graphics.FromImage (bitmap);
1003                         SolidBrush brush = new SolidBrush (Color.Red);
1004                         Rectangle[] rects = new Rectangle[2] {
1005                                 new Rectangle (5, 5, -10, -10), new Rectangle (0, 0, 5, -10)
1006                         };
1007                         RectangleF[] rectf = new RectangleF[2] {
1008                                 new RectangleF (0.0f, 5.0f, -10.0f, -10.0f), new RectangleF (15.0f, 0.0f, -10.0f, 5.0f)
1009                         };
1010                         g.FillRectangles (brush, rects);
1011                         g.FillRectangles (brush, rectf);
1012                         CheckForEmptyBitmap (bitmap);
1013                         brush.Dispose ();
1014                         g.Dispose ();
1015                         bitmap.Dispose ();
1016                 }
1017
1018                 private void CheckDefaultProperties (string message, Graphics g)
1019                 {
1020                         Assert.IsTrue (g.Clip.IsInfinite (g), message + ".Clip.IsInfinite");
1021                         AssertEquals (message + ".CompositingMode", CompositingMode.SourceOver, g.CompositingMode);
1022                         AssertEquals (message + ".CompositingQuality", CompositingQuality.Default, g.CompositingQuality);
1023                         AssertEquals (message + ".InterpolationMode", InterpolationMode.Bilinear, g.InterpolationMode);
1024                         AssertEquals (message + ".PageScale", 1.0f, g.PageScale);
1025                         AssertEquals (message + ".PageUnit", GraphicsUnit.Display, g.PageUnit);
1026                         AssertEquals (message + ".PixelOffsetMode", PixelOffsetMode.Default, g.PixelOffsetMode);
1027                         AssertEquals (message + ".SmoothingMode", SmoothingMode.None, g.SmoothingMode);
1028                         AssertEquals (message + ".TextContrast", 4, g.TextContrast);
1029                         AssertEquals (message + ".TextRenderingHint", TextRenderingHint.SystemDefault, g.TextRenderingHint);
1030                         Assert.IsTrue (g.Transform.IsIdentity, message + ".Transform.IsIdentity");
1031                 }
1032
1033                 private void CheckCustomProperties (string message, Graphics g)
1034                 {
1035                         Assert.IsFalse (g.Clip.IsInfinite (g), message + ".Clip.IsInfinite");
1036                         AssertEquals (message + ".CompositingMode", CompositingMode.SourceCopy, g.CompositingMode);
1037                         AssertEquals (message + ".CompositingQuality", CompositingQuality.HighQuality, g.CompositingQuality);
1038                         AssertEquals (message + ".InterpolationMode", InterpolationMode.HighQualityBicubic, g.InterpolationMode);
1039                         AssertEquals (message + ".PageScale", 0.5f, g.PageScale);
1040                         AssertEquals (message + ".PageUnit", GraphicsUnit.Inch, g.PageUnit);
1041                         AssertEquals (message + ".PixelOffsetMode", PixelOffsetMode.Half, g.PixelOffsetMode);
1042                         AssertEquals (message + ".RenderingOrigin", new Point (-1, -1), g.RenderingOrigin);
1043                         AssertEquals (message + ".SmoothingMode", SmoothingMode.AntiAlias, g.SmoothingMode);
1044                         AssertEquals (message + ".TextContrast", 0, g.TextContrast);
1045                         AssertEquals (message + ".TextRenderingHint", TextRenderingHint.AntiAlias, g.TextRenderingHint);
1046                         Assert.IsFalse (g.Transform.IsIdentity, message + ".Transform.IsIdentity");
1047                 }
1048
1049                 private void CheckMatrix (string message, Matrix m, float xx, float yx, float xy, float yy, float x0, float y0)
1050                 {
1051                         float[] elements = m.Elements;
1052                         AssertEquals (message + ".Matrix.xx", xx, elements[0], 0.01);
1053                         AssertEquals (message + ".Matrix.yx", yx, elements[1], 0.01);
1054                         AssertEquals (message + ".Matrix.xy", xy, elements[2], 0.01);
1055                         AssertEquals (message + ".Matrix.yy", yy, elements[3], 0.01);
1056                         AssertEquals (message + ".Matrix.x0", x0, elements[4], 0.01);
1057                         AssertEquals (message + ".Matrix.y0", y0, elements[5], 0.01);
1058                 }
1059
1060                 [Test]
1061                 public void BeginContainer ()
1062                 {
1063                         Bitmap bitmap = new Bitmap (20, 20);
1064                         Graphics g = Graphics.FromImage (bitmap);
1065
1066                         CheckDefaultProperties ("default", g);
1067                         AssertEquals ("default.RenderingOrigin", new Point (0, 0), g.RenderingOrigin);
1068
1069                         g.Clip = new Region (new Rectangle (10, 10, 10, 10));
1070                         g.CompositingMode = CompositingMode.SourceCopy;
1071                         g.CompositingQuality = CompositingQuality.HighQuality;
1072                         g.InterpolationMode = InterpolationMode.HighQualityBicubic;
1073                         g.PageScale = 0.5f;
1074                         g.PageUnit = GraphicsUnit.Inch;
1075                         g.PixelOffsetMode = PixelOffsetMode.Half;
1076                         g.RenderingOrigin = new Point (-1, -1);
1077                         g.RotateTransform (45);
1078                         g.SmoothingMode = SmoothingMode.AntiAlias;
1079                         g.TextContrast = 0;
1080                         g.TextRenderingHint = TextRenderingHint.AntiAlias;
1081                         CheckCustomProperties ("modified", g);
1082                         CheckMatrix ("modified.Transform", g.Transform, 0.707f, 0.707f, -0.707f, 0.707f, 0, 0);
1083
1084                         GraphicsContainer gc = g.BeginContainer ();
1085                         // things gets reseted after calling BeginContainer
1086                         CheckDefaultProperties ("BeginContainer", g);
1087                         // but not everything 
1088                         AssertEquals ("BeginContainer.RenderingOrigin", new Point (-1, -1), g.RenderingOrigin);
1089
1090                         g.EndContainer (gc);
1091                         CheckCustomProperties ("EndContainer", g);
1092                 }
1093
1094                 [Test]
1095                 public void BeginContainer_Rect ()
1096                 {
1097                         Bitmap bitmap = new Bitmap (20, 20);
1098                         Graphics g = Graphics.FromImage (bitmap);
1099
1100                         CheckDefaultProperties ("default", g);
1101                         AssertEquals ("default.RenderingOrigin", new Point (0, 0), g.RenderingOrigin);
1102
1103                         g.Clip = new Region (new Rectangle (10, 10, 10, 10));
1104                         g.CompositingMode = CompositingMode.SourceCopy;
1105                         g.CompositingQuality = CompositingQuality.HighQuality;
1106                         g.InterpolationMode = InterpolationMode.HighQualityBicubic;
1107                         g.PageScale = 0.5f;
1108                         g.PageUnit = GraphicsUnit.Inch;
1109                         g.PixelOffsetMode = PixelOffsetMode.Half;
1110                         g.RenderingOrigin = new Point (-1, -1);
1111                         g.RotateTransform (45);
1112                         g.SmoothingMode = SmoothingMode.AntiAlias;
1113                         g.TextContrast = 0;
1114                         g.TextRenderingHint = TextRenderingHint.AntiAlias;
1115                         CheckCustomProperties ("modified", g);
1116                         CheckMatrix ("modified.Transform", g.Transform, 0.707f, 0.707f, -0.707f, 0.707f, 0, 0);
1117
1118                         GraphicsContainer gc = g.BeginContainer (new Rectangle (10, 20, 30, 40), new Rectangle (10, 20, 300, 400), GraphicsUnit.Millimeter);
1119                         // things gets reseted after calling BeginContainer
1120                         CheckDefaultProperties ("BeginContainer", g);
1121                         // but not everything 
1122                         AssertEquals ("BeginContainer.RenderingOrigin", new Point (-1, -1), g.RenderingOrigin);
1123
1124                         g.EndContainer (gc);
1125                         CheckCustomProperties ("EndContainer", g);
1126                         CheckMatrix ("EndContainer.Transform", g.Transform, 0.707f, 0.707f, -0.707f, 0.707f, 0, 0);
1127                 }
1128
1129                 [Test]
1130                 public void BeginContainer_RectF ()
1131                 {
1132                         Bitmap bitmap = new Bitmap (20, 20);
1133                         Graphics g = Graphics.FromImage (bitmap);
1134
1135                         CheckDefaultProperties ("default", g);
1136                         AssertEquals ("default.RenderingOrigin", new Point (0, 0), g.RenderingOrigin);
1137
1138                         g.Clip = new Region (new Rectangle (10, 10, 10, 10));
1139                         g.CompositingMode = CompositingMode.SourceCopy;
1140                         g.CompositingQuality = CompositingQuality.HighQuality;
1141                         g.InterpolationMode = InterpolationMode.HighQualityBicubic;
1142                         g.PageScale = 0.5f;
1143                         g.PageUnit = GraphicsUnit.Inch;
1144                         g.PixelOffsetMode = PixelOffsetMode.Half;
1145                         g.RenderingOrigin = new Point (-1, -1);
1146                         g.RotateTransform (45);
1147                         g.SmoothingMode = SmoothingMode.AntiAlias;
1148                         g.TextContrast = 0;
1149                         g.TextRenderingHint = TextRenderingHint.AntiAlias;
1150                         CheckCustomProperties ("modified", g);
1151                         CheckMatrix ("modified.Transform", g.Transform, 0.707f, 0.707f, -0.707f, 0.707f, 0, 0);
1152
1153                         GraphicsContainer gc = g.BeginContainer (new RectangleF (40, 30, 20, 10), new RectangleF (10, 20, 30, 40), GraphicsUnit.Inch);
1154                         // things gets reseted after calling BeginContainer
1155                         CheckDefaultProperties ("BeginContainer", g);
1156                         // but not everything 
1157                         AssertEquals ("BeginContainer.RenderingOrigin", new Point (-1, -1), g.RenderingOrigin);
1158
1159                         g.EndContainer (gc);
1160                         CheckCustomProperties ("EndContainer", g);
1161                 }
1162
1163                 private void BeginContainer_GraphicsUnit (GraphicsUnit unit)
1164                 {
1165                         Bitmap bitmap = new Bitmap (20, 20);
1166                         Graphics g = Graphics.FromImage (bitmap);
1167                         g.BeginContainer (new RectangleF (40, 30, 20, 10), new RectangleF (10, 20, 30, 40), unit);
1168                 }
1169
1170                 [Test]
1171                 [ExpectedException (typeof (ArgumentException))]
1172                 public void BeginContainer_GraphicsUnit_Display ()
1173                 {
1174                         BeginContainer_GraphicsUnit (GraphicsUnit.Display);
1175                 }
1176
1177                 [Test]
1178                 public void BeginContainer_GraphicsUnit_Valid ()
1179                 {
1180                         BeginContainer_GraphicsUnit (GraphicsUnit.Document);
1181                         BeginContainer_GraphicsUnit (GraphicsUnit.Inch);
1182                         BeginContainer_GraphicsUnit (GraphicsUnit.Millimeter);
1183                         BeginContainer_GraphicsUnit (GraphicsUnit.Pixel);
1184                         BeginContainer_GraphicsUnit (GraphicsUnit.Point);
1185                 }
1186
1187                 [Test]
1188                 [ExpectedException (typeof (ArgumentException))]
1189                 public void BeginContainer_GraphicsUnit_World ()
1190                 {
1191                         BeginContainer_GraphicsUnit (GraphicsUnit.World);
1192                 }
1193
1194                 [Test]
1195                 [ExpectedException (typeof (ArgumentException))]
1196                 public void BeginContainer_GraphicsUnit_Bad ()
1197                 {
1198                         BeginContainer_GraphicsUnit ((GraphicsUnit)Int32.MinValue);
1199                 }
1200
1201                 [Test]
1202 #if NET_2_0
1203                 [ExpectedException (typeof (ArgumentNullException))]
1204 #else
1205                 [ExpectedException (typeof (NullReferenceException))]
1206 #endif
1207                 public void EndContainer_Null ()
1208                 {
1209                         Bitmap bitmap = new Bitmap (20, 20);
1210                         Graphics g = Graphics.FromImage (bitmap);
1211                         g.EndContainer (null);
1212                 }
1213
1214                 [Test]
1215                 public void Save ()
1216                 {
1217                         Bitmap bitmap = new Bitmap (20, 20);
1218                         Graphics g = Graphics.FromImage (bitmap);
1219
1220                         CheckDefaultProperties ("default", g);
1221                         AssertEquals ("default.RenderingOrigin", new Point (0, 0), g.RenderingOrigin);
1222
1223                         GraphicsState gs1 = g.Save ();
1224                         // nothing is changed after a save
1225                         CheckDefaultProperties ("save1", g);
1226                         AssertEquals ("save1.RenderingOrigin", new Point (0, 0), g.RenderingOrigin);
1227
1228                         g.Clip = new Region (new Rectangle (10, 10, 10, 10));
1229                         g.CompositingMode = CompositingMode.SourceCopy;
1230                         g.CompositingQuality = CompositingQuality.HighQuality;
1231                         g.InterpolationMode = InterpolationMode.HighQualityBicubic;
1232                         g.PageScale = 0.5f;
1233                         g.PageUnit = GraphicsUnit.Inch;
1234                         g.PixelOffsetMode = PixelOffsetMode.Half;
1235                         g.RenderingOrigin = new Point (-1, -1);
1236                         g.RotateTransform (45);
1237                         g.SmoothingMode = SmoothingMode.AntiAlias;
1238                         g.TextContrast = 0;
1239                         g.TextRenderingHint = TextRenderingHint.AntiAlias;
1240                         CheckCustomProperties ("modified", g);
1241                         CheckMatrix ("modified.Transform", g.Transform, 0.707f, 0.707f, -0.707f, 0.707f, 0, 0);
1242
1243                         GraphicsState gs2 = g.Save ();
1244                         CheckCustomProperties ("save2", g);
1245
1246                         g.Restore (gs2);
1247                         CheckCustomProperties ("restored1", g);
1248                         CheckMatrix ("restored1.Transform", g.Transform, 0.707f, 0.707f, -0.707f, 0.707f, 0, 0);
1249
1250                         g.Restore (gs1);
1251                         CheckDefaultProperties ("restored2", g);
1252                         AssertEquals ("restored2.RenderingOrigin", new Point (0, 0), g.RenderingOrigin);
1253                 }
1254
1255                 [Test]
1256                 [ExpectedException (typeof (NullReferenceException))]
1257                 public void Restore_Null ()
1258                 {
1259                         Bitmap bitmap = new Bitmap (20, 20);
1260                         Graphics g = Graphics.FromImage (bitmap);
1261                         g.Restore (null);
1262                 }
1263
1264                 [Test]
1265                 [ExpectedException (typeof (ArgumentNullException))]
1266                 public void FillRectangles_BrushNull_Rectangle ()
1267                 {
1268                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1269                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1270                                         g.FillRectangles (null, new Rectangle[1]);
1271                                 }
1272                         }
1273                 }
1274
1275                 [Test]
1276                 [ExpectedException (typeof (ArgumentNullException))]
1277                 public void FillRectangles_Rectangle_Null ()
1278                 {
1279                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1280                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1281                                         g.FillRectangles (Brushes.Red, (Rectangle[]) null);
1282                                 }
1283                         }
1284                 }
1285
1286                 [Test] // see bug #78408
1287                 [ExpectedException (typeof (ArgumentException))]
1288                 public void FillRectanglesZeroRectangle ()
1289                 {
1290                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1291                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1292                                         g.FillRectangles (Brushes.Red, new Rectangle[0]);
1293                                 }
1294                         }
1295                 }
1296
1297                 [Test]
1298                 [ExpectedException (typeof (ArgumentNullException))]
1299                 public void FillRectangles_BrushNull_RectangleF ()
1300                 {
1301                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1302                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1303                                         g.FillRectangles (null, new RectangleF[1]);
1304                                 }
1305                         }
1306                 }
1307
1308                 [Test]
1309                 [ExpectedException (typeof (ArgumentNullException))]
1310                 public void FillRectangles_RectangleF_Null ()
1311                 {
1312                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1313                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1314                                         g.FillRectangles (Brushes.Red, (RectangleF[])null);
1315                                 }
1316                         }
1317                 }
1318
1319                 [Test] // see bug #78408
1320                 [ExpectedException (typeof (ArgumentException))]
1321                 public void FillRectanglesZeroRectangleF ()
1322                 {
1323                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1324                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1325                                         g.FillRectangles (Brushes.Red, new RectangleF[0]);
1326                                 }
1327                         }
1328                 }
1329
1330                 [Test]
1331                 public void MeasureString_StringFont ()
1332                 {
1333                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1334                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1335                                         SizeF size = g.MeasureString (null, font);
1336                                         Assert.IsTrue (size.IsEmpty, "MeasureString(null,font)");
1337                                         size = g.MeasureString (String.Empty, font);
1338                                         Assert.IsTrue (size.IsEmpty, "MeasureString(empty,font)");
1339                                         // null font
1340                                         size = g.MeasureString (null, null);
1341                                         Assert.IsTrue (size.IsEmpty, "MeasureString(null,null)");
1342                                         size = g.MeasureString (String.Empty, null);
1343                                         Assert.IsTrue (size.IsEmpty, "MeasureString(empty,null)");
1344                                 }
1345                         }
1346                 }
1347
1348                 [Test]
1349                 [ExpectedException (typeof (ArgumentNullException))]
1350                 public void MeasureString_StringFont_Null ()
1351                 {
1352                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1353                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1354                                         g.MeasureString ("a", null);
1355                                 }
1356                         }
1357                 }
1358
1359                 [Test]
1360                 public void MeasureString_StringFontSizeF ()
1361                 {
1362                         if (font == null)
1363                                 Assert.Ignore ("Couldn't create required font");
1364
1365                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1366                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1367                                         SizeF size = g.MeasureString ("a", font, SizeF.Empty);
1368                                         Assert.IsFalse (size.IsEmpty, "MeasureString(a,font,empty)");
1369
1370                                         size = g.MeasureString (String.Empty, font, SizeF.Empty);
1371                                         Assert.IsTrue (size.IsEmpty, "MeasureString(empty,font,empty)");
1372                                 }
1373                         }
1374                 }
1375
1376                 [Test]
1377                 public void MeasureString_StringFontInt ()
1378                 {
1379                         if (font == null)
1380                                 Assert.Ignore ("Couldn't create required font");
1381
1382                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1383                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1384                                         SizeF size = g.MeasureString ("a", font, 0);
1385                                         Assert.IsFalse (size.IsEmpty, "MeasureString(a,font,0)");
1386                                         size = g.MeasureString ("a", font, Int32.MinValue);
1387                                         Assert.IsFalse (size.IsEmpty, "MeasureString(a,font,min)");
1388                                         size = g.MeasureString ("a", font, Int32.MaxValue);
1389                                         Assert.IsFalse (size.IsEmpty, "MeasureString(a,font,max)");
1390                                 }
1391                         }
1392                 }
1393
1394                 [Test]
1395                 public void MeasureString_Bug76664 ()
1396                 {
1397                         if (font == null)
1398                                 Assert.Ignore ("Couldn't create required font");
1399
1400                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1401                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1402                                         string s = "aaa aa aaaa a aaa";
1403                                         SizeF size = g.MeasureString (s, font);
1404
1405                                         int chars, lines;
1406                                         size = g.MeasureString (s, font, new SizeF (80, size.Height), null, out chars, out lines);
1407                                         // LAMESPEC: documentation seems to suggest chars is total length
1408                                         Assert.IsTrue (chars < s.Length, "characters fitted");
1409                                         AssertEquals ("lines fitted", 1, lines);
1410                                 }
1411                         }
1412                 }
1413
1414                 [Test]
1415                 public void MeasureCharacterRanges_NullOrEmptyText ()
1416                 {
1417                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1418                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1419                                         Region[] regions = g.MeasureCharacterRanges (null, font, new RectangleF (), null);
1420                                         AssertEquals ("text null", 0, regions.Length);
1421                                         regions = g.MeasureCharacterRanges (String.Empty, font, new RectangleF (), null);
1422                                         AssertEquals ("text empty", 0, regions.Length);
1423                                         // null font is ok with null or empty string
1424                                         regions = g.MeasureCharacterRanges (null, null, new RectangleF (), null);
1425                                         AssertEquals ("text null/null font", 0, regions.Length);
1426                                         regions = g.MeasureCharacterRanges (String.Empty, null, new RectangleF (), null);
1427                                         AssertEquals ("text empty/null font", 0, regions.Length);
1428                                 }
1429                         }
1430                 }
1431
1432                 [Test]
1433                 [ExpectedException (typeof (ArgumentNullException))]
1434                 public void MeasureCharacterRanges_FontNull ()
1435                 {
1436                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1437                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1438                                         g.MeasureCharacterRanges ("a", null, new RectangleF (), null);
1439                                 }
1440                         }
1441                 }
1442
1443                 [Test] // adapted from bug #78777
1444                 public void MeasureCharacterRanges_TwoLines ()
1445                 {
1446                         if (font == null)
1447                                 Assert.Ignore ("Couldn't create required font");
1448
1449                         string text = "this\nis a test";
1450                         CharacterRange[] ranges = new CharacterRange [2];
1451                         ranges[0] = new CharacterRange (0,5);
1452                         ranges[1] = new CharacterRange (5,9);
1453
1454                         StringFormat string_format = new StringFormat ();
1455                         string_format.FormatFlags = StringFormatFlags.NoClip;
1456                         string_format.SetMeasurableCharacterRanges (ranges);
1457
1458                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1459                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1460                                         SizeF size = g.MeasureString (text, font, new Point (0,0), string_format);
1461                                         RectangleF layout_rect = new RectangleF (0.0f, 0.0f, size.Width, size.Height);                  
1462                                         Region[] regions = g.MeasureCharacterRanges (text, font, layout_rect, string_format);
1463
1464                                         AssertEquals ("Length", 2, regions.Length);
1465                                         AssertEquals ("Height", regions[0].GetBounds (g).Height, regions[1].GetBounds (g).Height);
1466                                 }
1467                         }
1468                 }
1469
1470                 private void MeasureCharacterRanges (string text, int first, int length)
1471                 {
1472                         if (font == null)
1473                                 Assert.Ignore ("Couldn't create required font");
1474
1475                         CharacterRange[] ranges = new CharacterRange[1];
1476                         ranges[0] = new CharacterRange (first, length);
1477
1478                         StringFormat string_format = new StringFormat ();
1479                         string_format.FormatFlags = StringFormatFlags.NoClip;
1480                         string_format.SetMeasurableCharacterRanges (ranges);
1481
1482                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1483                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1484                                         SizeF size = g.MeasureString (text, font, new Point (0, 0), string_format);
1485                                         RectangleF layout_rect = new RectangleF (0.0f, 0.0f, size.Width, size.Height);
1486                                         g.MeasureCharacterRanges (text, font, layout_rect, string_format);
1487                                 }
1488                         }
1489                 }
1490
1491                 [Test]
1492                 [ExpectedException (typeof (ArgumentException))]
1493                 public void MeasureCharacterRanges_FirstTooFar ()
1494                 {
1495                         string text = "this\nis a test";
1496                         MeasureCharacterRanges (text, text.Length, 1);
1497                 }
1498
1499                 [Test]
1500                 [ExpectedException (typeof (ArgumentException))]
1501                 public void MeasureCharacterRanges_LengthTooLong ()
1502                 {
1503                         string text = "this\nis a test";
1504                         MeasureCharacterRanges (text, 0, text.Length + 1);
1505                 }
1506
1507                 [Test]
1508                 public void MeasureCharacterRanges_Prefix ()
1509                 {
1510                         if (font == null)
1511                                 Assert.Ignore ("Couldn't create required font");
1512
1513                         string text = "Hello &Mono::";
1514                         CharacterRange[] ranges = new CharacterRange[1];
1515                         ranges[0] = new CharacterRange (5, 4);
1516
1517                         StringFormat string_format = new StringFormat ();
1518                         string_format.SetMeasurableCharacterRanges (ranges);
1519
1520                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1521                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1522                                         SizeF size = g.MeasureString (text, font, new Point (0, 0), string_format);
1523                                         RectangleF layout_rect = new RectangleF (0.0f, 0.0f, size.Width, size.Height);
1524
1525                                         // here & is part of the measure and visible
1526                                         string_format.HotkeyPrefix = HotkeyPrefix.None;
1527                                         Region[] regions = g.MeasureCharacterRanges (text, font, layout_rect, string_format);
1528                                         RectangleF bounds_none = regions[0].GetBounds (g);
1529
1530                                         // here & is part of the measure (range) but visible as an underline
1531                                         string_format.HotkeyPrefix = HotkeyPrefix.Show;
1532                                         regions = g.MeasureCharacterRanges (text, font, layout_rect, string_format);
1533                                         RectangleF bounds_show = regions[0].GetBounds (g);
1534                                         Assert.IsTrue (bounds_show.Width < bounds_none.Width, "Show<None");
1535
1536                                         // here & is part of the measure (range) but invisible
1537                                         string_format.HotkeyPrefix = HotkeyPrefix.Hide;
1538                                         regions = g.MeasureCharacterRanges (text, font, layout_rect, string_format);
1539                                         RectangleF bounds_hide = regions[0].GetBounds (g);
1540                                         AssertEquals ("Hide==None", bounds_hide.Width, bounds_show.Width);
1541                                 }
1542                         }
1543                 }
1544
1545                 [Test]
1546                 public void DrawString_EndlessLoop_Bug77699 ()
1547                 {
1548                         if (font == null)
1549                                 Assert.Ignore ("Couldn't create required font");
1550
1551                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1552                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1553                                         Rectangle rect = Rectangle.Empty;
1554                                         rect.Location = new Point (10, 10);
1555                                         rect.Size = new Size (1, 20);
1556                                         StringFormat fmt = new StringFormat ();
1557                                         fmt.Alignment = StringAlignment.Center;
1558                                         fmt.LineAlignment = StringAlignment.Center;
1559                                         fmt.FormatFlags = StringFormatFlags.NoWrap;
1560                                         fmt.Trimming = StringTrimming.EllipsisWord;
1561                                         g.DrawString ("Test String", font, Brushes.Black, rect, fmt);
1562                                 }
1563                         }
1564                 }
1565
1566                 [Test]
1567                 public void DrawString_EndlessLoop_Wrapping ()
1568                 {
1569                         if (font == null)
1570                                 Assert.Ignore ("Couldn't create required font");
1571
1572                         using (Bitmap bitmap = new Bitmap (20, 20)) {
1573                                 using (Graphics g = Graphics.FromImage (bitmap)) {
1574                                         Rectangle rect = Rectangle.Empty;
1575                                         rect.Location = new Point (10, 10);
1576                                         rect.Size = new Size (1, 20);
1577                                         StringFormat fmt = new StringFormat ();
1578                                         fmt.Alignment = StringAlignment.Center;
1579                                         fmt.LineAlignment = StringAlignment.Center;
1580                                         fmt.Trimming = StringTrimming.EllipsisWord;
1581                                         g.DrawString ("Test String", font, Brushes.Black, rect, fmt);
1582                                 }
1583                         }
1584                 }
1585 #if NET_2_0
1586                 [Test]
1587                 public void TestReleaseHdc ()
1588                 {
1589                         Bitmap b = new Bitmap (100, 100);
1590                         Graphics g = Graphics.FromImage (b);
1591
1592                         g.GetHdc ();
1593                         g.ReleaseHdc ();
1594                         g.GetHdc ();
1595                         g.ReleaseHdc ();
1596                 }
1597
1598                 [Test]
1599                 [ExpectedException (typeof (ArgumentException))]
1600                 public void TestReleaseHdcException ()
1601                 {
1602                         Bitmap b = new Bitmap (100, 100);
1603                         Graphics g = Graphics.FromImage (b);
1604
1605                         g.ReleaseHdc ();
1606                 }
1607
1608                 [Test]
1609                 [ExpectedException (typeof (ArgumentException))]
1610                 public void TestReleaseHdcException2 ()
1611                 {
1612                         Bitmap b = new Bitmap (100, 100);
1613                         Graphics g = Graphics.FromImage (b);
1614
1615                         g.GetHdc ();
1616                         g.ReleaseHdc ();
1617                         g.ReleaseHdc ();
1618                 }
1619 #endif
1620         }
1621 }