Merge branch 'master' of git://github.com/mono/mono
[mono.git] / mcs / class / System.Drawing / System.Drawing / Graphics.jvm.cs
1 using System;
2 using System.Drawing.Drawing2D;
3 using System.Drawing.Imaging;
4 using System.Drawing.Text;
5 using System.ComponentModel;
6 using System.Collections;
7 using System.Runtime.InteropServices;
8 using System.Text;
9 using awt = java.awt;
10 using geom = java.awt.geom;
11
12 namespace System.Drawing {
13         [ComVisible(false)]
14         public sealed class Graphics : MarshalByRefObject, IDisposable {
15                 sealed class DummyStroke : awt.Stroke {
16                         #region Stroke Members
17
18                         awt.Shape awt.Stroke.createStrokedShape(awt.Shape arg_0) {
19                                 throw new NotImplementedException("DummyStroke");
20                         }
21
22                         #endregion
23                 }
24
25                 sealed class NormalizingPathIterator : geom.PathIterator {
26
27                         #region fields
28
29                         readonly geom.PathIterator _iter;
30
31                         const float norm = 0.5f;
32                         const float rnd = (1.0f - norm);
33                         float ax = 0.0f;
34                         float ay = 0.0f;
35
36                         #endregion
37
38                         #region ctor
39
40                         public NormalizingPathIterator(geom.PathIterator iter) {
41                                 _iter = iter;
42                         }
43
44                         #endregion
45
46                         #region methods
47
48                         static int GetIndex(int type) {
49                                 int index;
50                                 switch ((GraphicsPath.JPI)type) {
51                                         case GraphicsPath.JPI.SEG_CUBICTO:
52                                                 index = 4;
53                                                 break;
54                                         case GraphicsPath.JPI.SEG_QUADTO:
55                                                 index = 2;
56                                                 break;
57                                         case GraphicsPath.JPI.SEG_MOVETO:
58                                         case GraphicsPath.JPI.SEG_LINETO:
59                                                 index = 0;
60                                                 break;
61                                         case GraphicsPath.JPI.SEG_CLOSE:
62                                         default:
63                                                 index = -1;
64                                                 break;
65                                 }
66
67                                 return index;
68                         }
69
70                         #endregion
71
72                         #region PathIterator Members
73
74                         void geom.PathIterator.next() {
75                                 _iter.next();
76                         }
77
78                         bool geom.PathIterator.isDone() {
79                                 return _iter.isDone();
80                         }
81
82                         int geom.PathIterator.currentSegment(float[] point) {
83                                 int type = _iter.currentSegment(point);
84
85                                 int index = GetIndex(type);
86                                 
87                                 if (index >= 0) {
88                                         float ox = point[index];
89                                         float oy = point[index+1];
90                                         float newax = (float) java.lang.Math.floor(ox + rnd) + norm;
91                                         float neway = (float) java.lang.Math.floor(oy + rnd) + norm;
92                                         point[index] = newax;
93                                         point[index+1] = neway;
94                                         newax -= ox;
95                                         neway -= oy;
96                                         switch ((GraphicsPath.JPI)type) {
97                                                 case GraphicsPath.JPI.SEG_CUBICTO:
98                                                         point[0] += ax;
99                                                         point[1] += ay;
100                                                         point[2] += newax;
101                                                         point[3] += neway;
102                                                         break;
103                                                 case GraphicsPath.JPI.SEG_QUADTO:
104                                                         point[0] += (newax + ax) / 2;
105                                                         point[1] += (neway + ay) / 2;
106                                                         break;
107                                                         //                                                      case GraphicsPath.JPI.SEG_MOVETO:
108                                                         //                                                      case GraphicsPath.JPI.SEG_LINETO:
109                                                         //                                                      case GraphicsPath.JPI.SEG_CLOSE:
110                                                         //                                                              break;
111                                         }
112                                         ax = newax;
113                                         ay = neway;
114                                 }
115
116                                 return type;
117                         }
118
119                         int geom.PathIterator.currentSegment(double[] point) {
120                                 int type = _iter.currentSegment(point);
121
122                                 int index = GetIndex(type);
123
124                                 if (index >= 0) {
125                                         float ox = (float)point[index];
126                                         float oy = (float)point[index+1];
127                                         float newax = (float)java.lang.Math.floor(ox + rnd) + norm;
128                                         float neway = (float)java.lang.Math.floor(oy + rnd) + norm;
129                                         point[index] = newax;
130                                         point[index+1] = neway;
131                                         newax -= ox;
132                                         neway -= oy;
133                                         switch ((GraphicsPath.JPI)type) {
134                                                 case GraphicsPath.JPI.SEG_CUBICTO:
135                                                         point[0] += ax;
136                                                         point[1] += ay;
137                                                         point[2] += newax;
138                                                         point[3] += neway;
139                                                         break;
140                                                 case GraphicsPath.JPI.SEG_QUADTO:
141                                                         point[0] += (newax + ax) / 2;
142                                                         point[1] += (neway + ay) / 2;
143                                                         break;
144                                                         //                                                      case GraphicsPath.JPI.SEG_MOVETO:
145                                                         //                                                      case GraphicsPath.JPI.SEG_LINETO:
146                                                         //                                                      case GraphicsPath.JPI.SEG_CLOSE:
147                                                         //                                                              break;
148                                         }
149                                         ax = newax;
150                                         ay = neway;
151                                 }
152
153                                 return type;
154                         }
155
156                         int geom.PathIterator.getWindingRule() {
157                                 return _iter.getWindingRule();
158                         }
159
160                         #endregion
161
162                 }
163
164
165                 #region Variables
166
167                 readonly awt.Graphics2D _nativeObject;
168                 PixelOffsetMode _pixelOffsetMode = PixelOffsetMode.Default;
169                 int _textContrast = 4;
170                 TextRenderingHint _textRenderingHint;
171                 readonly Image _image;
172                 
173                 readonly Matrix _transform;
174                 GraphicsUnit _pageUnit = GraphicsUnit.Display;
175                 float _pageScale = 1.0f;
176
177                 readonly Region _clip;
178                 readonly awt.Rectangle _windowRect;
179
180                 GraphicsState _nextGraphicsState = null;
181
182                 static readonly float [] _unitConversion = {
183                                                                                                            1,                                                           // World
184                                                                                                            1,                                                           // Display
185                                                                                                            1,                                                           // Pixel
186                                                                                                            DefaultScreenResolution / 72.0f,     // Point
187                                                                                                            DefaultScreenResolution,                     // Inch
188                                                                                                            DefaultScreenResolution / 300.0f,// Document
189                                                                                                            DefaultScreenResolution / 25.4f      // Millimeter
190                                                                                                    };
191
192                 static int _isHeadless;
193                 static internal bool IsHeadless {
194                         get {
195                                 if (_isHeadless == 0) {
196                                         bool isHeadless = awt.GraphicsEnvironment.isHeadless();
197                                         if (!isHeadless) {
198                                                 try {
199                                                         awt.Toolkit.getDefaultToolkit();
200                                                 }
201                                                 catch{
202                                                         isHeadless = true;
203                                                 }
204                                         }
205
206                                         _isHeadless = isHeadless ? 2 : 1;
207                                 }
208
209                                 return _isHeadless > 1;
210                         }
211                 }
212         
213                 #endregion
214
215 #if INTPTR_SUPPORT
216                 [ComVisible(false)]
217                 public delegate bool EnumerateMetafileProc (EmfPlusRecordType recordType,
218                                                             int flags,
219                                                             int dataSize,
220                                                             IntPtr data,
221                                                             PlayRecordCallback callbackData);
222                 [ComVisible (false)]
223                         public delegate bool DrawImageAbort (IntPtr callbackData);              
224 #endif                  
225
226                 #region Constr. and Destr.
227                 private Graphics (Image image) {
228                         _nativeObject = (awt.Graphics2D)image.NativeObject.CurrentImage.NativeImage.getGraphics();
229                         _image = image;
230                         _transform = new Matrix ();
231
232                         NativeObject.setStroke(new DummyStroke());
233                         NativeObject.setRenderingHint(awt.RenderingHints.KEY_COLOR_RENDERING, awt.RenderingHints.VALUE_COLOR_RENDER_QUALITY);
234
235                         InterpolationMode = InterpolationMode.Bilinear;
236                         TextRenderingHint = TextRenderingHint.SystemDefault;
237
238                         _windowRect = new awt.Rectangle(_image.Width, _image.Height);
239                         _clip = new Region();
240                 }
241
242                 #endregion
243                 
244                 #region Internal Accessors
245
246                 static internal float [] UnitConversion {
247                         get {
248                                 return _unitConversion;
249                         }
250                 }
251                 
252                 static internal int DefaultScreenResolution {
253                         get {
254                                 return IsHeadless ? 96 :
255                                         awt.Toolkit.getDefaultToolkit().getScreenResolution();
256                         }
257                 }
258                 
259                 internal java.awt.Graphics2D NativeObject {
260                         get {
261                                 return _nativeObject;
262                         }
263                 }
264                 #endregion
265
266                 #region FromImage (static accessor)
267                 public static Graphics FromImage (Image image) {                
268                         return new Graphics(image);
269                 }
270                 #endregion
271
272
273                 #region Workers [INTERNAL]
274                 void DrawShape(Pen pen, awt.Shape shape) {
275                         if (pen == null)
276                                 throw new ArgumentNullException("pen");
277
278                         if (StrokeFactory.CanCreateAdvancedStroke && 
279                                 (!pen.CanCreateBasicStroke || !NeedsNormalization)) {
280                                 geom.AffineTransform oldT = NativeObject.getTransform();
281                                 NativeObject.setTransform(Matrix.IdentityTransform.NativeObject);
282
283                                 try {
284                                         geom.AffineTransform t = GetFinalTransform();
285                                         if (!oldT.isIdentity()) {
286                                                 t = (geom.AffineTransform)t.clone();
287                                                 t.preConcatenate(oldT);
288                                         }
289                                         
290                                         double widthsquared = pen.GetSquaredTransformedWidth(t);
291
292                                         bool antiAlias = (SmoothingMode == SmoothingMode.AntiAlias);
293
294                                         bool thin = (widthsquared <= (antiAlias ? 
295                                                 AdvancedStroke.MinPenSizeAASquared :
296                                                 AdvancedStroke.MinPenSizeSquared));
297
298                                         PenFit penFit = thin ? (antiAlias ? PenFit.ThinAntiAlias : PenFit.Thin) : PenFit.NotThin;
299
300                                         if (NeedsNormalization) {
301
302                                                 bool normThin = 
303                                                         widthsquared <= AdvancedStroke.MinPenSizeSquaredNorm;
304
305                                                 if (normThin) {
306                                                         shape = GetNormalizedShape(shape, t);
307                                                         shape = pen.GetNativeObject(
308                                                                 t, null, penFit).createStrokedShape(shape);
309                                                 }
310                                                 else {
311                                                         shape = pen.GetNativeObject(t, penFit).createStrokedShape(shape);
312                                                         shape = GetNormalizedShape(shape, null);
313                                                 }
314                                         }
315                                         else {
316                                                 shape = pen.GetNativeObject(t, penFit).createStrokedShape(shape);
317                                         }
318
319                                         FillScaledShape(pen.Brush, shape);
320                                 }
321                                 finally {
322                                         NativeObject.setTransform(oldT);
323                                 }
324                         }
325                         else {
326                                 awt.Stroke oldStroke = NativeObject.getStroke();
327                                 NativeObject.setStroke(pen.GetNativeObject(null, PenFit.NotThin));
328                                 try {
329
330                                         NativeObject.setPaint(pen.Brush);
331
332                                         geom.AffineTransform oldT = NativeObject.getTransform();
333                                         NativeObject.transform(GetFinalTransform());
334                                         try {
335                                                 NativeObject.draw(shape);
336                                         }
337                                         finally {
338                                                 NativeObject.setTransform(oldT);
339                                         }
340                                 }
341                                 finally {
342                                         NativeObject.setStroke(oldStroke);
343                                 }
344                         }
345                 }
346                 void FillShape(Brush paint, awt.Shape shape) {
347                         if (paint == null)
348                                 throw new ArgumentNullException("brush");
349
350                         geom.AffineTransform oldT = null;
351                         if (NeedsNormalization) {
352                                 oldT = NativeObject.getTransform();
353                                 geom.AffineTransform t = GetFinalTransform();
354                                 if (!oldT.isIdentity()) {
355                                         t = (geom.AffineTransform) t.clone ();
356                                         t.preConcatenate(oldT);
357                                 }
358                                 shape = GetNormalizedShape(shape, t);
359                         }
360                         else {
361                                 geom.AffineTransform t = GetFinalTransform();
362                                 if (!t.isIdentity())
363                                         shape = t.createTransformedShape(shape);
364                         }
365
366                         if (oldT != null)
367                                 NativeObject.setTransform(Matrix.IdentityTransform.NativeObject);
368
369                         try {
370                                 FillScaledShape(paint, shape);
371                         }
372                         finally {
373                                 if (oldT != null)
374                                         NativeObject.setTransform(oldT);
375                         }
376                 }
377
378                 bool NeedsNormalization {
379                         get {
380                                 return PixelOffsetMode != PixelOffsetMode.Half &&
381                                         PixelOffsetMode != PixelOffsetMode.HighQuality;
382                         }
383                 }
384
385                 static awt.Shape GetNormalizedShape(awt.Shape shape, geom.AffineTransform t) {
386                         geom.PathIterator iter = new NormalizingPathIterator(shape.getPathIterator(t));
387         
388                         geom.GeneralPath path = new geom.GeneralPath(iter.getWindingRule());
389                         path.append(iter, false);
390                         return path;
391                 }
392
393                 void FillScaledShape(Brush paint, awt.Shape shape) {
394                         Matrix m = null;
395                         if (!(paint is SolidBrush || paint is HatchBrush) && !_transform.IsIdentity) {
396                                 m = paint.BrushTransform;
397                                 paint.BrushMultiplyTransform( _transform );
398                         }
399
400                         try {
401                                 NativeObject.setPaint(paint);
402                                 NativeObject.fill(shape);
403                         }
404                         finally {
405                                 if (m != null)
406                                         paint.BrushTransform = m;
407                         }
408                 }
409
410                 #endregion
411
412                 #region Dispose
413                 public void Dispose() {                 
414                         NativeObject.dispose();
415                 }
416                 #endregion
417                 
418                 #region Clear
419                 public void Clear (Color color) {
420                         FillScaledShape(new SolidBrush( color ), _clip.NativeObject);
421                 }
422                 #endregion
423
424                 #region DrawArc
425                 public void DrawArc (Pen pen, Rectangle rect, float startAngle, float sweepAngle) {
426                         DrawArc (pen, 
427                                 rect.X, 
428                                 rect.Y, 
429                                 rect.Width, 
430                                 rect.Height, 
431                                 startAngle, 
432                                 sweepAngle);
433                 }
434
435                 
436                 public void DrawArc (Pen pen, RectangleF rect, float startAngle, float sweepAngle) {
437                         DrawArc (pen, 
438                                 rect.X, 
439                                 rect.Y, 
440                                 rect.Width, 
441                                 rect.Height, 
442                                 startAngle, 
443                                 sweepAngle);
444                 }
445
446                 public void DrawArc (Pen pen, int x, int y, int width, int height, int startAngle, int sweepAngle) {
447                         DrawArc(pen,
448                                 (float)x,
449                                 (float)y,
450                                 (float)width,
451                                 (float)height,
452                                 (float)startAngle,
453                                 (float)sweepAngle);
454                 }
455
456                 public void DrawArc (Pen pen, float x, float y, float width, float height, float startAngle, float sweepAngle) {
457                         GraphicsPath path = new GraphicsPath();
458                         path.AddArc(x, y, width, height, startAngle, sweepAngle);
459                         DrawPath(pen, path);
460                 }
461                 #endregion
462
463                 #region DrawBezier(s)
464                 public void DrawBezier (Pen pen, PointF pt1, PointF pt2, PointF pt3, PointF pt4) {
465                         DrawBezier(pen, pt1.X, pt1.Y, pt2.X, pt2.Y, pt3.X, pt3.Y, pt4.X, pt4.Y);
466                 }
467
468                 public void DrawBezier (Pen pen, Point pt1, Point pt2, Point pt3, Point pt4) {
469                         DrawBezier(pen, pt1.X, pt1.Y, pt2.X, pt2.Y, pt3.X, pt3.Y, pt4.X, pt4.Y);
470                 }
471
472                 public void DrawBezier (Pen pen, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {
473                         geom.GeneralPath path = new geom.GeneralPath();
474                         path.moveTo(x1,y1);
475                         path.curveTo(x2,y2,x3,y3,x4,y4);
476                         DrawShape(pen, path);
477                 }
478
479                 public void DrawBeziers (Pen pen, Point [] points) {
480                         GraphicsPath path = new GraphicsPath();
481                         path.AddBeziers(points);
482                         DrawPath(pen, path);
483                 }
484
485                 public void DrawBeziers (Pen pen, PointF [] points) {
486                         GraphicsPath path = new GraphicsPath();
487                         path.AddBeziers(points);
488                         DrawPath(pen, path);
489                 }
490                 #endregion 
491
492                 #region DrawClosedCurve
493                 public void DrawClosedCurve (Pen pen, PointF [] points) {
494                         DrawClosedCurve(pen, points, 0.5f, FillMode.Alternate);
495                 }
496                 
497                 public void DrawClosedCurve (Pen pen, Point [] points) {
498                         DrawClosedCurve(pen, points, 0.5f, FillMode.Alternate);
499                 }
500                         
501                 public void DrawClosedCurve (Pen pen, Point [] points, float tension, FillMode fillmode) {
502                         GraphicsPath path = new GraphicsPath(fillmode);
503                         path.AddClosedCurve(points, tension);
504                         DrawPath(pen, path);
505                 }
506                 
507                 public void DrawClosedCurve (Pen pen, PointF [] points, float tension, FillMode fillmode) {
508                         GraphicsPath path = new GraphicsPath(fillmode);
509                         path.AddClosedCurve(points, tension);
510                         DrawPath(pen, path);
511                 }
512                 #endregion
513
514                 #region DrawCurve
515                 public void DrawCurve (Pen pen, Point [] points) {
516                         DrawCurve(pen, points, 0.5f);
517                 }
518                 
519                 public void DrawCurve (Pen pen, PointF [] points) {
520                         DrawCurve(pen, points, 0.5f);
521                 }
522                 
523                 public void DrawCurve (Pen pen, PointF [] points, float tension) {
524                         DrawCurve(pen, points, 0, points.Length-1, tension);
525                 }
526                 
527                 public void DrawCurve (Pen pen, Point [] points, float tension) {
528                         DrawCurve(pen, points, 0, points.Length-1, tension);
529                 }
530                 
531                 
532                 public void DrawCurve (Pen pen, PointF [] points, int offset, int numberOfSegments) {
533                         DrawCurve(pen, points, offset, numberOfSegments, 0.5f);
534                 }
535
536                 public void DrawCurve (Pen pen, Point [] points, int offset, int numberOfSegments, float tension) {
537                         GraphicsPath path = new GraphicsPath();
538                         path.AddCurve(points, offset, numberOfSegments, tension);
539                         DrawPath(pen, path);
540                 }
541
542                 
543                 public void DrawCurve (Pen pen, PointF [] points, int offset, int numberOfSegments, float tension) {
544                         GraphicsPath path = new GraphicsPath();
545                         path.AddCurve(points, offset, numberOfSegments, tension);
546                         DrawPath(pen, path);
547                 }
548                 #endregion
549
550                 #region DrawEllipse
551                 public void DrawEllipse (Pen pen, Rectangle rect) {
552                         DrawEllipse (pen, rect.X, rect.Y, rect.Width, rect.Height);
553                 }
554
555                 public void DrawEllipse (Pen pen, RectangleF rect) {
556                         DrawEllipse (pen, rect.X, rect.Y, rect.Width, rect.Height);
557                 }
558
559                 public void DrawEllipse (Pen pen, int x, int y, int width, int height) {
560                         DrawEllipse(pen,(float)x,(float)y,(float)width,(float)height);
561                 }
562
563                 public void DrawEllipse (Pen pen, float x, float y, float width, float height) {
564                         DrawShape(pen, new geom.Ellipse2D.Float(x,y,width,height));
565                 }
566                 #endregion
567
568                 #region DrawIcon
569                 public void DrawIcon (Icon icon, Rectangle targetRect) {
570                         Bitmap b = icon.ToBitmap ();
571                         this.DrawImage (b, targetRect);
572                 }
573
574                 public void DrawIcon (Icon icon, int x, int y) {
575                         Bitmap b = icon.ToBitmap ();
576                         this.DrawImage (b, x, y);
577                 }
578
579                 public void DrawIconUnstretched (Icon icon, Rectangle targetRect) {
580                         Bitmap b = icon.ToBitmap ();
581                         this.DrawImageUnscaled (b, targetRect);
582                 }
583                 #endregion
584
585                 #region DrawImage
586
587                 public void DrawImage (Image image, Point point) {
588                         DrawImage(image, point.X, point.Y);
589                 }
590
591                 public void DrawImage (Image image, PointF point) {
592                         DrawImage(image, point.X, point.Y);
593                 }
594
595                 
596                 public void DrawImage (Image image, Point [] destPoints) {
597                         Matrix m = new Matrix(new Rectangle(0, 0, image.Width, image.Height), destPoints);
598                         DrawImage(image, m);
599                 }
600
601                 public void DrawImage (Image image, PointF [] destPoints) {
602                         Matrix m = new Matrix(new RectangleF(0, 0, image.Width, image.Height), destPoints);
603                         DrawImage(image, m);
604                 }
605
606                 
607                 public void DrawImage (Image image, Rectangle rect) {
608                         DrawImage(image, rect.X, rect.Y, rect.Width, rect.Height);
609                 }
610
611                 public void DrawImage (Image image, RectangleF rect) {
612                         DrawImage(image, rect.X, rect.Y, rect.Width, rect.Height);
613                 }
614
615                 
616                 public void DrawImage (Image image, int x, int y) {
617                         DrawImage(image, (float)x, (float)y);
618                 }
619
620                 public void DrawImage (Image image, float x, float y) {
621                         if ((image.HorizontalResolution != DpiX) || (image.VerticalResolution != DpiY))
622                                 DrawImage( image, x, y, 
623                                         (float)image.Width * (DpiX / image.HorizontalResolution) / _unitConversion[(int)PageUnit], 
624                                         (float)image.Height * (DpiY / image.VerticalResolution) / _unitConversion[(int)PageUnit]) ;
625                         else
626                                 DrawImage( image, x, y, 
627                                         (float)image.Width / _unitConversion[(int)PageUnit], 
628                                         (float)image.Height / _unitConversion[(int)PageUnit] );
629                 }
630
631                 
632                 public void DrawImage (Image image, Rectangle destRect, Rectangle srcRect, GraphicsUnit srcUnit) {
633                         DrawImage(
634                                 image,
635                                 new Point [] {
636                                                                  new Point( destRect.X, destRect.Y),
637                                                                  new Point( destRect.X + destRect.Width, destRect.Y),
638                                                                  new Point( destRect.X, destRect.Y + destRect.Height)},
639                                 srcRect, 
640                                 srcUnit);
641                 }
642         
643                 public void DrawImage (Image image, RectangleF destRect, RectangleF srcRect, GraphicsUnit srcUnit) {
644                         DrawImage(
645                                 image,
646                                 new PointF [] {
647                                                                  new PointF( destRect.X, destRect.Y),
648                                                                  new PointF( destRect.X + destRect.Width, destRect.Y),
649                                                                  new PointF( destRect.X, destRect.Y + destRect.Height)},
650                                 srcRect, 
651                                 srcUnit);
652                 }
653
654                 
655                 public void DrawImage (Image image, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit) {
656                         DrawImage(image, destPoints, srcRect, srcUnit, null);
657                 }
658
659                 public void DrawImage (Image image, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit) {
660                         DrawImage(image, destPoints, srcRect, srcUnit, null);
661                 }
662
663                 [MonoLimitation("ImageAttributes parameter is ignored.")]
664                 public void DrawImage (Image image, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr) {
665                         //TBD: ImageAttributes
666                         if (srcUnit != GraphicsUnit.Pixel)
667                                 throw new NotImplementedException();
668                         // Like in .NET http://dotnet247.com/247reference/msgs/45/227979.aspx
669
670                         Matrix mx = new Matrix(srcRect, destPoints);
671
672                         Region region = new Region(srcRect);
673                         DrawImage(image, mx, region);
674                 }
675
676                 [MonoLimitation ("ImageAttributes parameter is ignored.")]
677                 public void DrawImage (Image image, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr) {
678                         //TBD: ImageAttributes
679                         if (srcUnit != GraphicsUnit.Pixel)
680                                 throw new NotImplementedException();
681                         // Like in .NET http://dotnet247.com/247reference/msgs/45/227979.aspx
682
683                         Matrix mx = new Matrix(srcRect, destPoints);
684
685                         Region region = new Region(srcRect);
686                         DrawImage(image, mx, region);
687                 }
688
689
690                 public void DrawImage (Image image, int x, int y, int width, int height) {
691                         DrawImage(image, (float)x, (float)y, (float)width, (float)height);
692                 }
693
694                 public void DrawImage (Image image, float x, float y, float width, float height) {
695                         Matrix mx = new Matrix();
696                         mx.Translate((float)x, (float)y);
697                         mx.Scale(width / (float)image.Width, height / (float)image.Height);
698
699                         DrawImage( image, mx );
700                 }
701
702                 
703                 public void DrawImage (Image image, int x, int y, Rectangle srcRect, GraphicsUnit srcUnit) {                    
704                         DrawImage(image, new Rectangle(x, y, srcRect.Width, srcRect.Height), srcRect, srcUnit);
705                 }
706                 
707                 public void DrawImage (Image image, float x, float y, RectangleF srcRect, GraphicsUnit srcUnit) {       
708                         DrawImage(image, new RectangleF(x, y, srcRect.Width, srcRect.Height), srcRect, srcUnit);
709                 }
710
711
712                 public void DrawImage (Image image, Rectangle destRect, int srcX, int srcY, int srcWidth, int srcHeight, GraphicsUnit srcUnit) {
713                         DrawImage(image, destRect, srcX, srcY, srcWidth, srcHeight, srcUnit, null);
714                 }
715
716                 public void DrawImage (Image image, Rectangle destRect, float srcX, float srcY, float srcWidth, float srcHeight, GraphicsUnit srcUnit) {
717                         DrawImage(image, destRect, srcX, srcY, srcWidth, srcHeight, srcUnit, null);
718                 }
719
720                 [MonoLimitation ("ImageAttributes parameter is ignored.")]
721                 public void DrawImage (Image image, Rectangle destRect, int srcX, int srcY, int srcWidth, int srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttr) {                     
722                         //TBD: attributes
723                         DrawImage(
724                                 image, 
725                                 destRect,
726                                 new Rectangle(srcX, srcY, srcWidth, srcHeight),
727                                 srcUnit);
728                 }
729
730                 [MonoLimitation ("ImageAttributes parameter is ignored.")]
731                 public void DrawImage (Image image, Rectangle destRect, float srcX, float srcY, float srcWidth, float srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttrs) {
732                         //TBD: attributes
733                         DrawImage(
734                                 image, 
735                                 destRect,
736                                 new RectangleF(srcX, srcY, srcWidth, srcHeight),
737                                 srcUnit);
738                 }
739                 
740
741                 public delegate bool DrawImageAbort (IntPtr callbackdata);
742
743                 [MonoNotSupported ("")]
744                 public void DrawImage (Image image, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback)
745                 {
746                         throw new NotImplementedException ();
747                 }
748
749                 [MonoNotSupported ("")]
750                 public void DrawImage (Image image, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback)
751                 {
752                         throw new NotImplementedException ();
753                 }
754
755                 [MonoNotSupported ("")]
756                 public void DrawImage (Image image, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback, int callbackData)
757                 {
758                         throw new NotImplementedException ();
759                 }
760
761                 [MonoNotSupported ("")]
762                 public void DrawImage (Image image, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback, int callbackData)
763                 {
764                         throw new NotImplementedException ();
765                 }
766
767                 [MonoNotSupported ("")]
768                 public void DrawImage (Image image, Rectangle destRect, int srcX, int srcY, int srcWidth, int srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback)
769                 {
770                         throw new NotImplementedException ();
771                 }
772
773                 [MonoNotSupported ("")]
774                 public void DrawImage (Image image, Rectangle destRect, float srcX, float srcY, float srcWidth, float srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttrs, DrawImageAbort callback)
775                 {
776                         throw new NotImplementedException ();
777                 }
778
779                 [MonoNotSupported ("")]
780                 public void DrawImage (Image image, Rectangle destRect, int srcX, int srcY, int srcWidth, int srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttrs, DrawImageAbort callback, IntPtr callbackData)
781                 {
782                         throw new NotImplementedException ();
783                 }
784
785                 [MonoNotSupported ("")]
786                 public void DrawImage (Image image, Rectangle destRect, float srcX, float srcY, float srcWidth, float srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttrs, DrawImageAbort callback, IntPtr callbackData)
787                 {
788                         throw new NotImplementedException ();
789                 }
790
791                 internal void DrawImage (Image image, Matrix m) {
792                         DrawImage(image, m, null);
793                 }
794
795                 internal void DrawImage (Image image, Matrix m, Region clip) {
796                         if (clip == null) {
797                                 clip = new Region( new RectangleF( 0, 0, image.Width, image.Height ) );
798                         }
799
800                         geom.AffineTransform t = GetFinalTransform(_transform.NativeObject, PageUnit, 1.0f);
801                         if (!t.isIdentity())
802                                 m.NativeObject.preConcatenate(t);
803
804                                 clip.Transform( m );
805
806                         if (NeedsNormalization) {
807                                 Matrix normMatrix = ComputeClipNormalization(clip.GetBounds(this));
808                                 clip.Transform(normMatrix);
809                         }
810
811                         awt.Shape oldClip = NativeObject.getClip();
812                         IntersectScaledClipWithBase(clip);
813                         
814                         try {
815                                 Matrix mm = ComputeImageNormalization(image, m);
816                                 NativeObject.drawImage(image.NativeObject.CurrentImage.NativeImage, mm.NativeObject, null);
817                         }
818                         finally {
819                                 NativeObject.setClip( oldClip );
820                         }
821                 }
822
823                 private static Matrix ComputeImageNormalization(Image img, Matrix m) {
824                         if ( m.IsIdentity )
825                                 return m;
826
827                         //m.Translate( -(m.Elements[0] + m.Elements[2]) / 2.0f,  -(m.Elements[3] + m.Elements[1]) / 2.0f, MatrixOrder.Append);
828                         m.Translate( 
829                                 -(float)(m.NativeObject.getScaleX() + m.NativeObject.getShearX()) / 2.0f,  
830                                 -(float)(m.NativeObject.getScaleY() + m.NativeObject.getShearY()) / 2.0f, MatrixOrder.Append);
831                         
832                         PointF [] p = new PointF[] { 
833                                                                                    new PointF( 0, 0 ),
834                                                                                    new PointF( img.Width, 0 ),
835                                                                                    new PointF( 0, img.Height )};
836
837                         m.TransformPoints(p);
838                         for (int i=0; i < p.Length; i++) {
839                                 p[i].X = (float)( p[i].X + 0.5f );
840                                 p[i].Y = (float)( p[i].Y + 0.5f );
841                         }
842
843                         return new Matrix( new Rectangle(0, 0, img.Width, img.Height), p );
844                 }
845                 private static Matrix ComputeClipNormalization(RectangleF rect) {
846                         PointF [] p = new PointF[] { 
847                                                                                    new PointF( rect.X, rect.Y ),
848                                                                                    new PointF( rect.X + rect.Width, rect.Y ),
849                                                                                    new PointF( rect.X, rect.Y + rect.Height )};
850
851                         for (int i=0; i < p.Length; i++) {
852                                 p[i].X = (float)Math.Round( p[i].X + 0.5f ) + 0.5f;
853                                 p[i].Y = (float)Math.Round( p[i].Y + 0.5f ) + 0.5f;
854                         }
855
856                         return new Matrix( rect, p );
857                 }
858                 
859
860 #if INTPTR_SUPPORT
861                 [MonoTODO]
862                 public void DrawImage (Image image, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback)
863                 {
864                         throw new NotImplementedException();
865                 }
866
867                 [MonoTODO]
868                 public void DrawImage (Image image, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback)
869                 {
870                         
871                         throw new NotImplementedException();
872                 }
873
874                 [MonoTODO]
875                 public void DrawImage (Image image, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback, int callbackData)
876                 {
877                         throw new NotImplementedException();
878                 }
879 #endif
880
881 #if INTPTR_SUPPORT              
882                 [MonoTODO]
883                 public void DrawImage (Image image, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback, int callbackData)
884                 {
885                         throw new NotImplementedException();
886                 }
887 #endif
888
889 #if INTPTR_SUPPORT              
890                 public void DrawImage (Image image, Rectangle destRect, int srcX, int srcY, int srcWidth, int srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback)
891                 {
892                         //TBD:units,attributes, callback
893                         java.awt.Graphics2D g = (java.awt.Graphics2D)nativeObject;
894                         g.drawImage(image.NativeObject,destRect.X,destRect.Y,destRect.Width,destRect.Height,srcX,srcY,srcWidth,srcHeight,null);
895                 }
896                 
897                 public void DrawImage (Image image, Rectangle destRect, float srcX, float srcY, float srcWidth, float srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback)
898                 {
899                         //TBD:units,attributes, callback
900                         java.awt.Graphics2D g = (java.awt.Graphics2D)nativeObject;
901                         g.drawImage(image.NativeObject,
902                                 (int)destRect.X,
903                                 (int)destRect.Y,
904                                 (int)destRect.Width,
905                                 (int)destRect.Height,
906                                 (int)srcX,
907                                 (int)srcY,
908                                 (int)srcWidth,
909                                 (int)srcHeight,null);
910                 }
911
912                 public void DrawImage (Image image, Rectangle destRect, float srcX, float srcY, float srcWidth, float srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback, IntPtr callbackData)
913                 {
914                         //TBD:units,attributes, callback
915                         java.awt.Graphics2D g = (java.awt.Graphics2D)nativeObject;
916                         g.drawImage(image.NativeObject,
917                                 (int)destRect.X,
918                                 (int)destRect.Y,
919                                 (int)destRect.Width,
920                                 (int)destRect.Height,
921                                 (int)srcX,
922                                 (int)srcY,
923                                 (int)srcWidth,
924                                 (int)srcHeight,null);
925                 }
926                 
927                 public void DrawImage (Image image, Rectangle destRect, int srcX, int srcY, int srcWidth, int srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback, IntPtr callbackData)
928                 {
929                         //TBD:units,attributes, callback
930                         java.awt.Graphics2D g = (java.awt.Graphics2D)nativeObject;
931                         g.drawImage(image.NativeObject,
932                                 destRect.X,
933                                 destRect.Y,
934                                 destRect.Width,
935                                 destRect.Height,
936                                 srcX,
937                                 srcY,
938                                 srcWidth,
939                                 srcHeight,null);
940                 }               
941 #endif
942                 
943                 public void DrawImageUnscaled (Image image, Point point) 
944                 {
945                         DrawImageUnscaled (image, point.X, point.Y);
946                 }
947                 
948                 public void DrawImageUnscaled (Image image, Rectangle rect) {
949                         DrawImageUnscaled (image, rect.X, rect.Y, rect.Width, rect.Height);
950                 }
951                 
952                 public void DrawImageUnscaled (Image image, int x, int y) {
953                         DrawImage (image, x, y, image.Width, image.Height);
954                 }
955
956                 public void DrawImageUnscaled (Image image, int x, int y, int width, int height) {
957                         Image tmpImg = new Bitmap (width, height);
958                         Graphics g = FromImage (tmpImg);
959                         g.DrawImage (image, 0, 0, image.Width, image.Height);
960                         this.DrawImage (tmpImg, x, y, width, height);
961                         tmpImg.Dispose ();
962                         g.Dispose ();           
963                 }
964
965 #if NET_2_0
966                 [MonoNotSupported ("")]
967                 public void DrawImageUnscaledAndClipped (Image image, Rectangle rect)
968                 {
969                         throw new NotImplementedException ();
970                 }
971
972 #endif
973                 #endregion
974
975                 #region DrawLine
976                 public void DrawLine (Pen pen, PointF pt1, PointF pt2) {
977                         DrawLine(pen,pt1.X,pt1.Y,pt2.X,pt2.Y);
978                 }
979
980                 public void DrawLine (Pen pen, Point pt1, Point pt2) {
981                         DrawLine(pen,(float)pt1.X,(float)pt1.Y,(float)pt2.X,(float)pt2.Y);
982                 }
983
984                 public void DrawLine (Pen pen, int x1, int y1, int x2, int y2) {
985                         DrawLine(pen,(float)x1,(float)y1,(float)x2,(float)y2);
986                 }
987
988                 public void DrawLine (Pen pen, float x1, float y1, float x2, float y2) {
989                         DrawShape(pen, new geom.Line2D.Float(x1,y1,x2,y2));
990                 }
991
992                 public void DrawLines (Pen pen, PointF [] points) {
993                         GraphicsPath path = new GraphicsPath();
994                         path.AddLines(points);
995                         DrawShape(pen, path);
996                 }
997
998                 public void DrawLines (Pen pen, Point [] points) {
999                         GraphicsPath path = new GraphicsPath();
1000                         path.AddLines(points);
1001                         DrawShape(pen, path);
1002                 }
1003                 #endregion
1004
1005                 #region DrawPath
1006                 public void DrawPath (Pen pen, GraphicsPath path) {
1007                         DrawShape(pen, path);
1008                 }
1009                 #endregion
1010                 
1011                 #region DrawPie
1012                 public void DrawPie (Pen pen, Rectangle rect, float startAngle, float sweepAngle) {
1013                         DrawPie (pen, rect.X, rect.Y, rect.Width, rect.Height, startAngle, sweepAngle);
1014                 }
1015                 
1016                 public void DrawPie (Pen pen, RectangleF rect, float startAngle, float sweepAngle) {
1017                         DrawPie (pen, rect.X, rect.Y, rect.Width, rect.Height, startAngle, sweepAngle);
1018                 }
1019                 
1020                 public void DrawPie (Pen pen, float x, float y, float width, float height, float startAngle, float sweepAngle) {
1021                         GraphicsPath path = new GraphicsPath();
1022                         path.AddPie(x, y, width, height, startAngle, sweepAngle);
1023                         DrawPath(pen, path);
1024                 }
1025                 
1026                 public void DrawPie (Pen pen, int x, int y, int width, int height, int startAngle, int sweepAngle) {
1027                         DrawPie(pen,(float)x,(float)y,(float)width,(float)height,(float)startAngle,(float)sweepAngle);
1028                 }
1029                 #endregion
1030
1031                 #region DrawPolygon
1032                 public void DrawPolygon (Pen pen, Point [] points) {
1033                         GraphicsPath path = new GraphicsPath();
1034                         path.AddPolygon(points);
1035                         DrawPath(pen, path);
1036                 }
1037
1038                 public void DrawPolygon (Pen pen, PointF [] points) {
1039                         GraphicsPath path = new GraphicsPath();
1040                         path.AddPolygon(points);
1041                         DrawPath(pen, path);
1042                 }
1043                 #endregion
1044
1045                 #region DrawRectangle(s)
1046                 internal void DrawRectangle (Pen pen, RectangleF rect) {
1047                         DrawRectangle (pen, rect.Left, rect.Top, rect.Width, rect.Height);
1048                 }
1049
1050                 public void DrawRectangle (Pen pen, Rectangle rect) {
1051                         DrawRectangle (pen, rect.Left, rect.Top, rect.Width, rect.Height);
1052                 }
1053
1054                 public void DrawRectangle (Pen pen, float x, float y, float width, float height) {
1055                         DrawShape(pen, new geom.Rectangle2D.Float(x,y,width,height));
1056                 }
1057
1058                 public void DrawRectangle (Pen pen, int x, int y, int width, int height) {
1059                         DrawRectangle (pen,(float) x,(float) y,(float) width,(float) height);
1060                 }
1061
1062                 public void DrawRectangles (Pen pen, RectangleF [] rects) {
1063                         foreach(RectangleF r in rects)
1064                                 DrawRectangle (pen, r.Left, r.Top, r.Width, r.Height);
1065                 }
1066
1067                 public void DrawRectangles (Pen pen, Rectangle [] rects) {
1068                         foreach(Rectangle r in rects)
1069                                 DrawRectangle (pen, r.Left, r.Top, r.Width, r.Height);
1070                 }
1071                 #endregion
1072
1073                 #region DrawString
1074                 public void DrawString (string s, Font font, Brush brush, RectangleF layoutRectangle) {                 
1075                         DrawString(s, font, brush, layoutRectangle.X, layoutRectangle.Y, layoutRectangle.Width, layoutRectangle.Height, null);
1076                 }
1077                 
1078                 public void DrawString (string s, Font font, Brush brush, PointF point) {
1079                         DrawString(s, font, brush, point.X, point.Y, float.PositiveInfinity, float.PositiveInfinity, null);
1080                 }
1081                 
1082                 public void DrawString (string s, Font font, Brush brush, PointF point, StringFormat format) {
1083                         DrawString(s, font, brush, point.X, point.Y, float.PositiveInfinity, float.PositiveInfinity, format);
1084                 }
1085
1086                 public void DrawString (string s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format) {
1087                         DrawString(s, font, brush, layoutRectangle.X, layoutRectangle.Y, layoutRectangle.Width, layoutRectangle.Height, format);
1088                 }
1089
1090                 public void DrawString (string s, Font font, Brush brush, float x, float y) {
1091                         DrawString(s, font, brush, x, y, float.PositiveInfinity, float.PositiveInfinity, null);
1092                 }
1093
1094                 public void DrawString (string s, Font font, Brush brush, float x, float y, StringFormat format) {
1095                         DrawString(s, font, brush, x, y, float.PositiveInfinity, float.PositiveInfinity, format);
1096                 }
1097
1098                 void DrawString (string s, Font font, Brush brush, 
1099                         float x, float y, float width, float height, 
1100                         StringFormat format) {
1101                         if (brush == null)
1102                                 throw new ArgumentNullException("brush");
1103
1104                         if (font == null)
1105                                 throw new ArgumentNullException("font");
1106
1107                         if (format != null && format.LineAlignment != StringAlignment.Near) {
1108
1109                                 SizeF sizeF = MeasureString(s, font, format, width, height, null);
1110
1111                                 float lineAWidth = width;
1112                                 float lineAHeight = height;
1113
1114                                 if (float.IsPositiveInfinity(width))
1115                                         lineAWidth = lineAHeight = 0;
1116
1117                                 float wdelta = format.IsVertical ? lineAWidth - sizeF.Width : lineAHeight - sizeF.Height;
1118                                 float pdelta = format.LineAlignment == StringAlignment.Center ? wdelta/2 : wdelta;
1119                                 if (format.IsVertical) {
1120                                         if (!(format.IsRightToLeft && format.LineAlignment == StringAlignment.Far))
1121                                                 x += pdelta;
1122                                         if (!float.IsPositiveInfinity(width))
1123                                                 width -= wdelta;
1124                                 }
1125                                 else {
1126                                         y += pdelta;
1127                                         if (!float.IsPositiveInfinity(width))
1128                                                 height -= wdelta;
1129                                 }
1130                         }
1131
1132                         awt.Paint oldP = NativeObject.getPaint();
1133                         NativeObject.setPaint(brush);
1134                         try {
1135                                 geom.AffineTransform oldT = NativeObject.getTransform();                                
1136                                 try {
1137
1138                                         bool noclip = float.IsPositiveInfinity(width) || (format != null && format.NoClip);
1139
1140                                         awt.Shape oldClip = null;
1141                                         if (!noclip) {
1142                                                 oldClip = NativeObject.getClip();
1143                                                 NativeObject.clip(new geom.Rectangle2D.Float(x, y, width, height));
1144                                         }
1145                                         try {
1146                                                 TextLineIterator iter = new TextLineIterator(s, font, NativeObject.getFontRenderContext(), format, width, height);
1147                                                 NativeObject.transform(iter.Transform);
1148                                                 for (LineLayout layout = iter.NextLine(); layout != null; layout = iter.NextLine()) {
1149                                                         layout.Draw (NativeObject, x * UnitConversion [(int) PageUnit], y * UnitConversion [(int) PageUnit]);
1150                                                 }
1151                                         }
1152                                         finally {
1153                                                 if (!noclip)
1154                                                         NativeObject.setClip(oldClip);
1155                                         }
1156                                 }
1157                                 finally {
1158                                         NativeObject.setTransform(oldT);
1159                                 }
1160                         }
1161                         finally {
1162                                 NativeObject.setPaint(oldP);
1163                         }
1164                 }
1165                 #endregion
1166
1167                 #region Container
1168
1169                 void PushGraphicsState(GraphicsState state) {
1170                         state.Next = _nextGraphicsState;
1171                         _nextGraphicsState = state;
1172                 }
1173
1174                 GraphicsState PopGraphicsState() {
1175                         GraphicsState state = _nextGraphicsState;
1176                         _nextGraphicsState = _nextGraphicsState.Next;
1177                         return state;
1178                 }
1179
1180                 bool ContainsGraphicsState(GraphicsState state) {
1181                         GraphicsState gs = _nextGraphicsState;
1182
1183                         while(gs != null) {
1184                                 if (gs == state)
1185                                         return true;
1186
1187                                 gs = gs.Next;
1188                         }
1189
1190                         return false;
1191                 }
1192
1193                 public void EndContainer (GraphicsContainer container) {
1194                         Restore(container.StateObject);
1195                 }
1196
1197                 public GraphicsContainer BeginContainer () {
1198                         return new GraphicsContainer(Save(Matrix.IdentityTransform, true));
1199                 }
1200                 
1201                 public GraphicsContainer BeginContainer (Rectangle dstrect, Rectangle srcrect, GraphicsUnit unit) {
1202                         Matrix containerTransfrom =
1203                                 new Matrix(     srcrect,
1204                                 new Point [] {   new Point (dstrect.X, dstrect.Y), 
1205                                                                  new Point (dstrect.X + dstrect.Width, dstrect.Y), 
1206                                                                  new Point (dstrect.X, dstrect.Y + dstrect.Height) });
1207
1208                         float scale = _unitConversion[ (int)PageUnit ] / _unitConversion[ (int)unit ];
1209                         containerTransfrom.Scale(scale, scale);
1210
1211                         return new GraphicsContainer(Save(containerTransfrom, true));
1212                 }
1213
1214                 
1215                 public GraphicsContainer BeginContainer (RectangleF dstrect, RectangleF srcrect, GraphicsUnit unit) {
1216                         Matrix containerTransfrom =
1217                                 new Matrix(     srcrect,
1218                                 new PointF [] {  new PointF (dstrect.X, dstrect.Y), 
1219                                                                  new PointF (dstrect.X + dstrect.Width, dstrect.Y), 
1220                                                                  new PointF (dstrect.X, dstrect.Y + dstrect.Height) });
1221
1222                         float scale = _unitConversion[ (int)PageUnit ] / _unitConversion[ (int)unit ];
1223                         containerTransfrom.Scale(scale, scale);
1224
1225                         return new GraphicsContainer(Save(containerTransfrom, true));
1226                 }
1227
1228                 GraphicsState Save(Matrix matrix, bool resetState) {
1229                         GraphicsState graphicsState = new GraphicsState(this, matrix, resetState);
1230
1231                         PushGraphicsState( graphicsState );
1232                         return graphicsState;
1233                 }
1234
1235                 public GraphicsState Save () {
1236                         return Save(Matrix.IdentityTransform, false);
1237                 }
1238
1239                 public void Restore (GraphicsState graphicsState) {
1240                         if (ContainsGraphicsState(graphicsState)) {
1241                                 GraphicsState gs = PopGraphicsState();
1242                                 while ( gs != graphicsState )
1243                                         gs = PopGraphicsState();
1244
1245                                 graphicsState.RestoreState(this);
1246                         }
1247                 }
1248
1249                 #endregion
1250
1251                 #region Metafiles Staff
1252                 [MonoTODO]
1253                 public void AddMetafileComment (byte [] data) {
1254                         throw new NotImplementedException ();
1255                 }
1256
1257 #if INTPTR_SUPPORT
1258                 [MonoTODO]
1259                 public void EnumerateMetafile (Metafile metafile, Point [] destPoints, EnumerateMetafileProc callback)
1260                 {
1261                         throw new NotImplementedException ();
1262                 }
1263
1264                 [MonoTODO]
1265                 public void EnumerateMetafile (Metafile metafile, RectangleF destRect, EnumerateMetafileProc callback)
1266                 {
1267                         throw new NotImplementedException ();
1268                 }
1269
1270                 [MonoTODO]
1271                 public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, EnumerateMetafileProc callback)
1272                 {
1273                         throw new NotImplementedException ();
1274                 }
1275
1276                 [MonoTODO]
1277                 public void EnumerateMetafile (Metafile metafile, Rectangle destRect, EnumerateMetafileProc callback)
1278                 {
1279                         throw new NotImplementedException ();
1280                 }
1281
1282                 [MonoTODO]
1283                 public void EnumerateMetafile (Metafile metafile, Point destPoint, EnumerateMetafileProc callback)
1284                 {
1285                         throw new NotImplementedException ();
1286                 }
1287
1288                 [MonoTODO]
1289                 public void EnumerateMetafile (Metafile metafile, PointF destPoint, EnumerateMetafileProc callback)
1290                 {
1291                         throw new NotImplementedException ();
1292                 }
1293
1294                 [MonoTODO]
1295                 public void EnumerateMetafile (Metafile metafile, PointF destPoint, EnumerateMetafileProc callback, IntPtr callbackData)
1296                 {
1297                         throw new NotImplementedException ();
1298                 }
1299
1300                 [MonoTODO]
1301                 public void EnumerateMetafile (Metafile metafile, Rectangle destRect, EnumerateMetafileProc callback, IntPtr callbackData)
1302                 {
1303                         throw new NotImplementedException ();
1304                 }
1305
1306                 [MonoTODO]
1307                 public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, EnumerateMetafileProc callback, IntPtr callbackData)
1308                 {
1309                         throw new NotImplementedException ();
1310                 }
1311
1312                 [MonoTODO]
1313                 public void EnumerateMetafile (Metafile metafile, Point destPoint, EnumerateMetafileProc callback, IntPtr callbackData)
1314                 {
1315                         throw new NotImplementedException ();
1316                 }
1317
1318                 [MonoTODO]
1319                 public void EnumerateMetafile (Metafile metafile, Point [] destPoints, EnumerateMetafileProc callback, IntPtr callbackData)
1320                 {
1321                         throw new NotImplementedException ();
1322                 }
1323
1324                 [MonoTODO]
1325                 public void EnumerateMetafile (Metafile metafile, RectangleF destRect, EnumerateMetafileProc callback, IntPtr callbackData)
1326                 {
1327                         throw new NotImplementedException ();
1328                 }
1329
1330                 [MonoTODO]
1331                 public void EnumerateMetafile (Metafile metafile, PointF destPoint, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)
1332                 {
1333                         throw new NotImplementedException ();
1334                 }
1335
1336                 [MonoTODO]
1337                 public void EnumerateMetafile (Metafile metafile, Point destPoint, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)
1338                 {
1339                         throw new NotImplementedException ();
1340                 }
1341
1342                 [MonoTODO]
1343                 public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)
1344                 {
1345                         throw new NotImplementedException ();
1346                 }
1347
1348                 [MonoTODO]
1349                 public void EnumerateMetafile (Metafile metafile, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)
1350                 {
1351                         throw new NotImplementedException ();
1352                 }
1353
1354                 [MonoTODO]
1355                 public void EnumerateMetafile (Metafile metafile, RectangleF destRect, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)
1356                 {
1357                         throw new NotImplementedException ();
1358                 }
1359
1360                 [MonoTODO]
1361                 public void EnumerateMetafile (Metafile metafile, Rectangle destRect, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)
1362                 {
1363                         throw new NotImplementedException ();
1364                 }
1365
1366                 [MonoTODO]
1367                 public void EnumerateMetafile (Metafile metafile, RectangleF destRect, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
1368                 {
1369                         throw new NotImplementedException ();
1370                 }
1371
1372                 [MonoTODO]
1373                 public void EnumerateMetafile (Metafile metafile, Point destPoint, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
1374                 {
1375                         throw new NotImplementedException ();
1376                 }
1377
1378                 [MonoTODO]
1379                 public void EnumerateMetafile (Metafile metafile, PointF destPoint, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
1380                 {
1381                         throw new NotImplementedException ();
1382                 }
1383
1384                 [MonoTODO]
1385                 public void EnumerateMetafile (Metafile metafile, Point [] destPoints, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
1386                 {
1387                         throw new NotImplementedException ();
1388                 }
1389
1390                 [MonoTODO]
1391                 public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
1392                 {
1393                         throw new NotImplementedException ();
1394                 }
1395
1396                 [MonoTODO]
1397                 public void EnumerateMetafile (Metafile metafile, Rectangle destRect, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
1398                 {
1399                         throw new NotImplementedException ();
1400                 }
1401
1402                 [MonoTODO]
1403                 public void EnumerateMetafile (Metafile metafile, Rectangle destRect, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)
1404                 {
1405                         throw new NotImplementedException ();
1406                 }
1407
1408                 [MonoTODO]
1409                 public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)
1410                 {
1411                         throw new NotImplementedException ();
1412                 }
1413
1414                 [MonoTODO]
1415                 public void EnumerateMetafile (Metafile metafile, RectangleF destRect, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)
1416                 {
1417                         throw new NotImplementedException ();
1418                 }
1419
1420                 [MonoTODO]
1421                 public void EnumerateMetafile (Metafile metafile, PointF destPoint, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)
1422                 {
1423                         throw new NotImplementedException ();
1424                 }
1425
1426                 [MonoTODO]
1427                 public void EnumerateMetafile (Metafile metafile, Point destPoint, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)
1428                 {
1429                         throw new NotImplementedException ();
1430                 }
1431
1432                 [MonoTODO]
1433                 public void EnumerateMetafile (Metafile metafile, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)
1434                 {
1435                         throw new NotImplementedException ();
1436                 }
1437
1438                 [MonoTODO]
1439                 public void EnumerateMetafile (Metafile metafile, Point [] destPoints, Rectangle srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
1440                 {
1441                         throw new NotImplementedException ();
1442                 }
1443
1444                 [MonoTODO]
1445                 public void EnumerateMetafile (Metafile metafile, Rectangle destRect, Rectangle srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
1446                 {
1447                         throw new NotImplementedException ();
1448                 }
1449
1450                 [MonoTODO]
1451                 public void EnumerateMetafile (Metafile metafile, Point destPoint, Rectangle srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
1452                 {
1453                         throw new NotImplementedException ();
1454                 }
1455
1456                 [MonoTODO]
1457                 public void EnumerateMetafile (Metafile metafile, RectangleF destRect, RectangleF srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
1458                 {
1459                         throw new NotImplementedException ();
1460                 }
1461
1462                 [MonoTODO]
1463                 public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, RectangleF srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
1464                 {
1465                         throw new NotImplementedException ();
1466                 }
1467
1468                 [MonoTODO]
1469                 public void EnumerateMetafile (Metafile metafile, PointF destPoint, RectangleF srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)
1470                 {
1471                         throw new NotImplementedException ();
1472                 }
1473 #endif  
1474                 #endregion      
1475
1476                 #region ExcludeClip
1477                 void ExcludeClip(geom.Area area) {
1478
1479                         geom.AffineTransform t = GetFinalTransform();
1480                         if (!t.isIdentity()) {
1481                                 area = (geom.Area) area.clone ();
1482                                 area.transform(t);
1483                         }
1484
1485                         _clip.NativeObject.subtract(area);
1486                         RestoreBaseClip();
1487                         NativeObject.clip(_clip);
1488                 }
1489
1490                 public void ExcludeClip (Rectangle rect) {
1491                         ExcludeClip(new geom.Area(rect.NativeObject));
1492                 }
1493
1494                 public void ExcludeClip (Region region) {
1495                         if (region == null)
1496                                 throw new ArgumentNullException("region");
1497                         ExcludeClip(region.NativeObject);
1498                 }
1499                 #endregion 
1500
1501                 #region FillClosedCurve
1502                 public void FillClosedCurve (Brush brush, PointF [] points) {
1503                         FillClosedCurve (brush, points, FillMode.Alternate);
1504                 }
1505
1506                 
1507                 public void FillClosedCurve (Brush brush, Point [] points) {
1508                         FillClosedCurve (brush, points, FillMode.Alternate);
1509                 }
1510
1511                 
1512                 public void FillClosedCurve (Brush brush, PointF [] points, FillMode fillmode) {
1513                         FillClosedCurve (brush, points, fillmode, 0.5f);
1514                 }
1515                 
1516                 public void FillClosedCurve (Brush brush, Point [] points, FillMode fillmode) {
1517                         FillClosedCurve (brush, points, fillmode, 0.5f);
1518                 }
1519
1520                 public void FillClosedCurve (Brush brush, PointF [] points, FillMode fillmode, float tension) {
1521                         GraphicsPath path = new GraphicsPath(fillmode);
1522                         path.AddClosedCurve(points, tension);
1523                         FillPath(brush, path);
1524                 }
1525
1526                 public void FillClosedCurve (Brush brush, Point [] points, FillMode fillmode, float tension) {
1527                         GraphicsPath path = new GraphicsPath(fillmode);
1528                         path.AddClosedCurve(points, tension);
1529                         FillPath(brush, path);
1530                 }
1531                 #endregion
1532
1533                 #region FillEllipse
1534                 public void FillEllipse (Brush brush, Rectangle rect) {
1535                         FillEllipse (brush, rect.X, rect.Y, rect.Width, rect.Height);
1536                 }
1537
1538                 public void FillEllipse (Brush brush, RectangleF rect) {
1539                         FillEllipse (brush, rect.X, rect.Y, rect.Width, rect.Height);
1540                 }
1541
1542                 public void FillEllipse (Brush brush, float x, float y, float width, float height) {
1543                         FillShape(brush,new java.awt.geom.Ellipse2D.Float(x,y,width,height));
1544                 }
1545
1546                 public void FillEllipse (Brush brush, int x, int y, int width, int height) {
1547                         FillEllipse (brush,(float)x,(float)y,(float)width,(float)height);
1548                 }
1549                 #endregion
1550
1551                 #region FillPath
1552                 public void FillPath (Brush brush, GraphicsPath path) {
1553                         if (path == null)
1554                                 throw new ArgumentNullException("path");
1555
1556                         FillShape(brush,path);
1557                 }
1558                 #endregion
1559
1560                 #region FillPie
1561                 public void FillPie (Brush brush, Rectangle rect, float startAngle, float sweepAngle) {
1562                         FillPie(brush,(float)rect.X,(float)rect.Y,(float)rect.Width,(float)rect.Height,(float)startAngle,(float)sweepAngle);
1563                 }
1564
1565                 public void FillPie (Brush brush, int x, int y, int width, int height, int startAngle, int sweepAngle) {
1566                         FillPie(brush,(float)x,(float)y,(float)width,(float)height,(float)startAngle,(float)sweepAngle);
1567                 }
1568
1569                 public void FillPie (Brush brush, float x, float y, float width, float height, float startAngle, float sweepAngle) {
1570                         GraphicsPath path = new GraphicsPath();
1571                         path.AddPie(x, y, width, height, startAngle, sweepAngle);
1572                         FillPath(brush, path);
1573                 }
1574                 #endregion
1575
1576                 #region FillPolygon
1577                 public void FillPolygon (Brush brush, PointF [] points) {
1578                         FillPolygon(brush, points, FillMode.Alternate);
1579                 }
1580
1581                 public void FillPolygon (Brush brush, Point [] points) {
1582                         FillPolygon(brush, points, FillMode.Alternate);
1583                 }
1584
1585                 public void FillPolygon (Brush brush, Point [] points, FillMode fillMode) {
1586                         GraphicsPath path = new GraphicsPath(fillMode);
1587                         path.AddPolygon(points);
1588                         FillPath(brush,path);
1589                 }
1590
1591                 public void FillPolygon (Brush brush, PointF [] points, FillMode fillMode) {
1592                         GraphicsPath path = new GraphicsPath(fillMode);
1593                         path.AddPolygon(points);
1594                         FillPath(brush,path);
1595                 }
1596                 #endregion
1597
1598                 #region FillRectangle
1599                 public void FillRectangle (Brush brush, RectangleF rect) {
1600                         FillRectangle (brush, rect.Left, rect.Top, rect.Width, rect.Height);
1601                 }
1602
1603                 public void FillRectangle (Brush brush, Rectangle rect) {
1604                         FillRectangle (brush, rect.Left, rect.Top, rect.Width, rect.Height);
1605                 }
1606
1607                 public void FillRectangle (Brush brush, int x, int y, int width, int height) {
1608                         FillRectangle(brush,(float)x,(float)y,(float)width,(float)height);
1609                 }
1610
1611                 public void FillRectangle (Brush brush, float x, float y, float width, float height) {
1612                         FillShape(brush,new java.awt.geom.Rectangle2D.Float(x,y,width,height));
1613                 }
1614
1615                 public void FillRectangles (Brush brush, Rectangle [] rects) {
1616                         GraphicsPath path = new GraphicsPath();
1617                         path.AddRectangles(rects);
1618                         FillPath(brush,path);
1619                 }
1620
1621                 public void FillRectangles (Brush brush, RectangleF [] rects) {
1622                         GraphicsPath path = new GraphicsPath();
1623                         path.AddRectangles(rects);
1624                         FillPath(brush,path);
1625                 }
1626                 #endregion
1627
1628                 #region FillRegion
1629                 public void FillRegion (Brush brush, Region region) {
1630                         FillShape(brush,region);
1631                 }
1632
1633                 #endregion
1634
1635                 public void Flush () {
1636                         Flush (FlushIntention.Flush);
1637                 }
1638
1639                 
1640                 public void Flush (FlushIntention intention) {
1641                         if (_image != null)
1642                                 _image.NativeObject.CurrentImage.NativeImage.flush();
1643                 }
1644
1645 #if INTPTR_SUPPORTED
1646                 [EditorBrowsable (EditorBrowsableState.Advanced)]
1647                 [MonoTODO]
1648                 public void ReleaseHdc (IntPtr hdc)
1649                 {
1650                         throw new NotImplementedException();
1651                 }
1652
1653                 [EditorBrowsable (EditorBrowsableState.Advanced)]
1654                 [MonoTODO]
1655                 public void ReleaseHdcInternal (IntPtr hdc)
1656                 {
1657                         throw new NotImplementedException ();
1658                 }
1659
1660                 [EditorBrowsable (EditorBrowsableState.Advanced)]               
1661                 [MonoTODO]
1662                 public static Graphics FromHdc (IntPtr hdc)
1663                 {
1664                         throw new NotImplementedException();
1665                 }
1666
1667                 [EditorBrowsable (EditorBrowsableState.Advanced)]
1668                 [MonoTODO]
1669                 public static Graphics FromHdc (IntPtr hdc, IntPtr hdevice)
1670                 {
1671                         throw new NotImplementedException ();
1672                 }
1673
1674                 [EditorBrowsable (EditorBrowsableState.Advanced)]
1675                 [MonoTODO]
1676                 public static Graphics FromHdcInternal (IntPtr hdc)
1677                 {
1678                         throw new NotImplementedException ();
1679                 }
1680
1681                 [EditorBrowsable (EditorBrowsableState.Advanced)]               
1682                 [MonoTODO]
1683                 public static Graphics FromHwnd (IntPtr hwnd)
1684                 {
1685                         throw new NotImplementedException();
1686                 }
1687
1688                 [EditorBrowsable (EditorBrowsableState.Advanced)]
1689                 [MonoTODO]
1690                 public static Graphics FromHwndInternal (IntPtr hwnd)
1691                 {
1692                         throw new NotImplementedException ();
1693                 }
1694
1695                 [MonoTODO]
1696                 internal static Graphics FromXDrawable (IntPtr drawable, IntPtr display)
1697                 {
1698                         throw new NotImplementedException();
1699                 }
1700
1701                 [MonoTODO]
1702                 public static IntPtr GetHalftonePalette ()
1703                 {
1704                         throw new NotImplementedException ();
1705                 }
1706
1707                 [EditorBrowsable (EditorBrowsableState.Advanced)]
1708                 [MonoTODO]
1709                 public IntPtr GetHdc ()
1710                 {
1711                         throw new NotImplementedException();
1712                 }
1713 #endif
1714                 
1715                 #region GetNearestColor
1716                 [MonoTODO]
1717                 public Color GetNearestColor (Color color) {
1718                         throw new NotImplementedException();
1719                 }
1720                 #endregion
1721
1722                 #region IntersectClip
1723                 void IntersectClip (geom.Area area) {
1724                         
1725                         geom.AffineTransform t = GetFinalTransform();
1726                         if (!t.isIdentity()) {
1727                                 area = (geom.Area) area.clone ();
1728                                 area.transform(t);
1729                         }
1730
1731                         _clip.NativeObject.intersect(area);
1732                         RestoreBaseClip();
1733                         NativeObject.clip(_clip);
1734                 }
1735
1736                 public void IntersectClip (Region region) {
1737                         if (region == null)
1738                                 throw new ArgumentNullException("region");
1739
1740                         IntersectClip(region.NativeObject);
1741                 }
1742                 
1743                 public void IntersectClip (RectangleF rect) {
1744                         IntersectClip(new geom.Area(rect.NativeObject));
1745                 }
1746
1747                 public void IntersectClip (Rectangle rect) {                    
1748                         IntersectClip(new geom.Area(rect.NativeObject));
1749                 }
1750                 #endregion
1751
1752                 #region IsVisible
1753                 public bool IsVisible (Point point) {
1754                         return IsVisible(point.X,point.Y);
1755                 }
1756
1757                 
1758                 public bool IsVisible (RectangleF rect) {
1759                         return IsVisible ((float)rect.X,(float)rect.Y,(float)rect.Width,(float)rect.Height);
1760                 }
1761
1762                 public bool IsVisible (PointF point) {
1763                         return IsVisible(point.X,point.Y);
1764                 }
1765                 
1766                 public bool IsVisible (Rectangle rect) {
1767                         return IsVisible ((float)rect.X,(float)rect.Y,(float)rect.Width,(float)rect.Height);
1768                 }
1769                 
1770                 public bool IsVisible (float x, float y) {
1771                         double dx = x;
1772                         double dy = y;
1773                         geom.AffineTransform t = GetFinalTransform();
1774                         if (!t.isIdentity()) {
1775                                 double[] p = new double[] {dx, dy};
1776                                 t.transform(p, 0, p, 0, 1);
1777
1778                                 dx = p[0];
1779                                 dy = p[1];
1780                         }
1781                         if (!_clip.NativeObject.contains(dx, dy))
1782                                 return false;
1783
1784                         awt.Shape clip = NativeObject.getClip();
1785                         if (clip == null)
1786                                 return true;
1787
1788                         return clip.contains(dx, dy);
1789                 }
1790                 
1791                 public bool IsVisible (int x, int y) {
1792                         return IsVisible ((float)x,(float)y);
1793                 }
1794                 
1795                 public bool IsVisible (float x, float y, float width, float height) {
1796
1797                         geom.AffineTransform t = GetFinalTransform();
1798                         geom.Rectangle2D r = new geom.Rectangle2D.Float(x, y, width, height);
1799                         
1800                         if (!t.isIdentity())
1801                                 r = t.createTransformedShape(r).getBounds2D();
1802                 
1803                         return NativeObject.hitClip(
1804                                         (int)(r.getX()+0.5), (int)(r.getY()+0.5),
1805                                         (int)(r.getWidth()+0.5), (int)(r.getHeight()+0.5))
1806                                 && _clip.NativeObject.intersects(r);
1807                 }
1808
1809                 
1810                 public bool IsVisible (int x, int y, int width, int height) {
1811                         return IsVisible ((float)x,(float)y,(float)width,(float)height);
1812                 }
1813                 #endregion
1814
1815                 #region MeasureCharacterRanges
1816                 public Region [] MeasureCharacterRanges (string text, Font font, RectangleF layoutRect, StringFormat stringFormat) {
1817                         if (stringFormat == null)
1818                                 throw new ArgumentException("stringFormat");
1819
1820                         CharacterRange[] ranges = stringFormat.CharRanges;
1821                         if (ranges == null || ranges.Length == 0)
1822                                 return new Region[0];
1823
1824                         GraphicsPath[] pathes = new GraphicsPath[ranges.Length];
1825                         for (int i = 0; i < pathes.Length; i++)
1826                                 pathes[i] = new GraphicsPath();
1827
1828                         TextLineIterator iter = new TextLineIterator(text, font, NativeObject.getFontRenderContext(),
1829                                 stringFormat, layoutRect.Width, layoutRect.Height);
1830                         
1831                         for (LineLayout layout = iter.NextLine(); layout != null; layout = iter.NextLine()) {
1832
1833                                 for (int i = 0; i < ranges.Length; i++) {
1834                                         int start = ranges[i].First;
1835                                         int length = ranges[i].Length;
1836                                         start -= iter.CharsConsumed;
1837                                         int limit = start + length;
1838                                         int layoutStart = iter.CurrentPosition - layout.CharacterCount;
1839                                         if (start < iter.CurrentPosition && limit > layoutStart) {
1840
1841                                                 float layoutOffset;
1842                                                 if (start > layoutStart)
1843                                                         layoutOffset = iter.GetAdvanceBetween(layoutStart, start);
1844                                                 else {
1845                                                         layoutOffset = 0;
1846                                                         start = layoutStart;
1847                                                 }
1848
1849                                                 float width = (limit < iter.CurrentPosition) ?
1850                                                         iter.GetAdvanceBetween(start, limit) :
1851                                                         layout.Width - layoutOffset;
1852
1853                                                 float height = layout.Ascent + layout.Descent;
1854
1855                                                 float x = layout.NativeX;
1856                                                 float y = layout.NativeY;
1857
1858                                                 if (stringFormat.IsVertical) {
1859                                                         y += layoutOffset;
1860                                                         x -= layout.Descent;
1861                                                 }
1862                                                 else {
1863                                                         x += layoutOffset;
1864                                                         y -= layout.Ascent;
1865                                                 }
1866
1867                                                 if (layout.AccumulatedHeight + height > iter.WrapHeight) {
1868                                                         float diff = iter.WrapHeight - layout.AccumulatedHeight;
1869                                                         if (stringFormat.IsVertical && stringFormat.IsRightToLeft) {
1870                                                                 x += diff;
1871                                                                 height -= diff;
1872                                                         }
1873                                                         else
1874                                                                 height = diff;
1875                                                 }
1876
1877                                                 if (stringFormat.IsVertical)
1878                                                         pathes[i].AddRectangle(x + layoutRect.X, y + layoutRect.Y, height, width);
1879                                                 else
1880                                                         pathes[i].AddRectangle(x + layoutRect.X, y + layoutRect.Y, width, height);
1881                                         }
1882                                 }
1883                         }
1884
1885                         geom.AffineTransform lineAlignT = iter.CalcLineAlignmentTransform();
1886                         if (lineAlignT != null) {
1887                                 for (int i = 0; i < pathes.Length; i++)
1888                                         pathes[i].NativeObject.transform(lineAlignT);
1889                         }
1890
1891                         Region[] regions = new Region[ranges.Length];
1892                         for (int i = 0; i < regions.Length; i++)
1893                                 regions[i] = new Region(pathes[i]);
1894
1895                         return regions;
1896                 }
1897                 #endregion
1898                 
1899                 #region MeasureString
1900                 public SizeF MeasureString (string text, Font font) {
1901                         return MeasureString(text, font, null, float.PositiveInfinity, float.PositiveInfinity, null); 
1902                 }
1903
1904                 
1905                 public SizeF MeasureString (string text, Font font, SizeF layoutArea) {
1906                         return MeasureString(text, font, layoutArea, null);
1907                 }
1908
1909                 
1910                 public SizeF MeasureString (string text, Font font, int width) {
1911                         return MeasureString(text, font, width, null);
1912                 }
1913
1914
1915                 public SizeF MeasureString (string text, Font font, SizeF layoutArea, StringFormat format) {
1916                         return MeasureString(text, font, format, layoutArea.Width, layoutArea.Height, null);
1917                 }
1918
1919                 
1920                 public SizeF MeasureString (string text, Font font, int width, StringFormat format) {
1921                         return MeasureString(text, font, format, width, float.PositiveInfinity, null);
1922                 }
1923
1924                 
1925                 public SizeF MeasureString (string text, Font font, PointF origin, StringFormat format) {
1926                         return MeasureString(text, font, format, float.PositiveInfinity, float.PositiveInfinity, null);
1927                 }
1928
1929                 SizeF MeasureString (string text, Font font, StringFormat format, float width, float height, int[] statistics) {
1930
1931                         if (statistics != null) {
1932                                 statistics[0] = 0;
1933                                 statistics[1] = 0;
1934                         }
1935
1936                         TextLineIterator iter = new TextLineIterator(text, font, NativeObject.getFontRenderContext(), format, width, height);
1937
1938                         float mwidth = 0;
1939                         int linesFilled = 0;
1940                         for (LineLayout layout = iter.NextLine(); layout != null; layout = iter.NextLine()) {
1941
1942                                 linesFilled ++;
1943                                 float w = layout.MeasureWidth;
1944
1945                                 if (w > mwidth)
1946                                         mwidth = w;
1947                         }
1948
1949                         if (linesFilled == 0)
1950                                 return SizeF.Empty;
1951
1952                         float mheight = iter.AccumulatedHeight;
1953
1954                         if (format != null) {
1955                                 if (format.IsVertical) {
1956                                         float temp = mheight;
1957                                         mheight = mwidth;
1958                                         mwidth = temp;
1959                                 }
1960                         }
1961
1962                         if (!(format != null && format.NoClip)) {
1963                                 if (mwidth > width)
1964                                         mwidth = width;
1965                                 if (mheight > height)
1966                                         mheight = height;
1967                         }
1968
1969                         if (statistics != null) {
1970                                 statistics[0] = linesFilled;
1971                                 statistics[1] = iter.CharsConsumed;
1972                         }
1973
1974                         return new SizeF (mwidth / UnitConversion [(int) _pageUnit], mheight / UnitConversion [(int) _pageUnit]);
1975                 }
1976
1977                 
1978                 public SizeF MeasureString (string text, Font font, SizeF layoutArea, StringFormat stringFormat, out int charactersFitted, out int linesFilled) {       
1979                         linesFilled = 0;
1980                         charactersFitted = 0;
1981
1982                         int[] statistics = new int[2];
1983                         SizeF sz = MeasureString(text, font, stringFormat, layoutArea.Width, layoutArea.Height, statistics);
1984                         linesFilled = statistics[0];
1985                         charactersFitted = statistics[1];
1986                         return sz;
1987                 }
1988                 #endregion
1989
1990                 #region MultiplyTransform
1991                 public void MultiplyTransform (Matrix matrix) {
1992                         MultiplyTransform (matrix, MatrixOrder.Prepend);
1993                 }
1994
1995                 public void MultiplyTransform (Matrix matrix, MatrixOrder order) {
1996                         ConcatenateTransform(matrix.NativeObject, order);
1997                 }
1998                 #endregion
1999
2000                 #region Reset (Clip and Transform)
2001                 public void ResetClip () {
2002                         _clip.MakeInfinite();
2003                         RestoreBaseClip();
2004                         NativeObject.clip(_clip);
2005                 }
2006
2007                 public void ResetTransform () {
2008                         _transform.Reset();
2009                 }
2010                 #endregion
2011
2012                 #region RotateTransform
2013                 public void RotateTransform (float angle) {
2014                         RotateTransform (angle, MatrixOrder.Prepend);
2015                 }
2016
2017                 public void RotateTransform (float angle, MatrixOrder order) {
2018                         ConcatenateTransform(
2019                                 geom.AffineTransform.getRotateInstance(java.lang.Math.toRadians(angle)),
2020                                 order);
2021                 }
2022                 #endregion
2023
2024                 #region ScaleTransform
2025                 public void ScaleTransform (float sx, float sy) {
2026                         ScaleTransform (sx, sy, MatrixOrder.Prepend);
2027                 }
2028
2029                 public void ScaleTransform (float sx, float sy, MatrixOrder order) {
2030                         ConcatenateTransform(
2031                                 geom.AffineTransform.getScaleInstance(sx, sy),
2032                                 order);
2033                 }
2034                 #endregion
2035
2036                 #region SetClip [Must be reviewed - more abstraction needed]
2037                 public void SetClip (RectangleF rect) {
2038                         SetClip (rect, CombineMode.Replace);
2039                 }
2040
2041                 public void SetClip (GraphicsPath path) {
2042                         SetClip (path, CombineMode.Replace);
2043                 }
2044
2045                 public void SetClip (Rectangle rect) {
2046                         SetClip (rect, CombineMode.Replace);
2047                 }
2048
2049                 public void SetClip (Graphics g) {
2050                         SetClip (g, CombineMode.Replace);
2051                 }
2052
2053                 public void SetClip (Graphics g, CombineMode combineMode) {
2054                         if(g == null)
2055                                 throw new NullReferenceException();
2056                         
2057                         CombineClipArea(g._clip.NativeObject, combineMode);
2058                 }
2059
2060                 public void SetClip (Rectangle rect, CombineMode combineMode) {
2061                         SetClip(rect.X,rect.Y,rect.Width,rect.Height,combineMode);                      
2062                 }               
2063                 public void SetClip (RectangleF rect, CombineMode combineMode) {                        
2064                         SetClip(rect.X,rect.Y,rect.Width,rect.Height,combineMode);                      
2065                 }
2066                 
2067                 public void SetClip (Region region, CombineMode combineMode) {
2068                         if(region == null)
2069                                 throw new ArgumentNullException("region");
2070
2071                         CombineClipArea ((geom.Area) region.NativeObject.clone (), combineMode);
2072                 }
2073                 
2074                 public void SetClip (GraphicsPath path, CombineMode combineMode) {
2075                         if(path == null)
2076                                 throw new ArgumentNullException("path");
2077
2078                         CombineClipArea(new geom.Area(path.NativeObject), combineMode);
2079                 }
2080                 #endregion
2081
2082                 #region Clipping Staff [INTERNAL]
2083                 internal Region ScaledClip {
2084                         get {
2085                                 return _clip.Clone();
2086                         }
2087                         set {
2088                                 _clip.NativeObject.reset();
2089                                 _clip.NativeObject.add(value.NativeObject);
2090                         }
2091                 }
2092                 internal void SetClip(float x,float y,float width,float height,CombineMode combineMode) {                                       
2093                         CombineClipArea(new geom.Area(
2094                                 new geom.Rectangle2D.Float(x,y,width,height)),combineMode);
2095                 }
2096
2097                 void CombineClipArea(geom.Area area, CombineMode combineMode) {
2098                         geom.AffineTransform t = GetFinalTransform();
2099                         if (!t.isIdentity())
2100                                 area.transform(t);
2101                         if (combineMode == CombineMode.Replace) {
2102                                 _clip.NativeObject.reset();
2103                                 _clip.NativeObject.add(area);
2104                         }
2105                         else {
2106                                 geom.Area curClip = _clip.NativeObject;
2107                                 switch(combineMode) {
2108                                         case CombineMode.Complement:
2109                                                 curClip.add(area);
2110                                                 break;
2111                                         case CombineMode.Exclude:
2112                                                 curClip.subtract(area);
2113                                                 break;
2114                                         case CombineMode.Intersect:
2115                                                 curClip.intersect(area);
2116                                                 break;
2117                                         case CombineMode.Union:
2118                                                 curClip.add(area);
2119                                                 break;
2120                                         case CombineMode.Xor:
2121                                                 curClip.exclusiveOr(area);
2122                                                 break;
2123                                         default:
2124                                                 throw new ArgumentOutOfRangeException();                                        
2125                                 }
2126                         }
2127
2128                         RestoreBaseClip();
2129                         NativeObject.clip(_clip);
2130                 }
2131
2132                 internal void IntersectScaledClipWithBase(awt.Shape clip) {
2133                         NativeObject.clip(clip);
2134                 }
2135
2136                 void RestoreBaseClip() {
2137                         if (_nextGraphicsState == null) {
2138                                 NativeObject.setClip(_windowRect);
2139                                 return;
2140                         }
2141
2142                         _nextGraphicsState.RestoreBaseClip(this);
2143                 }
2144                 
2145                 #endregion
2146                 
2147                 #region TransformPoints
2148                 [MonoTODO]
2149                 public void TransformPoints (CoordinateSpace destSpace, CoordinateSpace srcSpace, PointF [] pts) {
2150                         //TBD:CoordinateSpace
2151                         java.awt.geom.AffineTransform tr = this.Transform.NativeObject;
2152                         float[] fpts = new float[2];
2153                         for(int i = 0; i< pts.Length; i++) {
2154                                 fpts[0] = pts[i].X;
2155                                 fpts[1] = pts[i].Y;
2156                                 tr.transform(fpts, 0, fpts, 0, 1);
2157                                 pts[i].X = fpts[0];
2158                                 pts[i].Y = fpts[1];
2159                         }
2160                 }
2161
2162                 [MonoTODO]
2163                 public void TransformPoints (CoordinateSpace destSpace, CoordinateSpace srcSpace, Point [] pts) {                                               
2164                         //TBD:CoordinateSpace
2165                         java.awt.geom.AffineTransform tr = this.Transform.NativeObject;
2166                         float[] fpts = new float[2];
2167                         for(int i = 0; i< pts.Length; i++) {
2168                                 fpts[0] = pts[i].X;
2169                                 fpts[1] = pts[i].Y;
2170                                 tr.transform(fpts, 0, fpts, 0, 1);
2171                                 pts[i].X = (int)fpts[0];
2172                                 pts[i].Y = (int)fpts[1];
2173                         }
2174                 }
2175                 #endregion
2176
2177                 #region TranslateClip
2178                 public void TranslateClip (int dx, int dy) {
2179                         TranslateClip((float)dx, (float)dy);
2180                 }
2181
2182                 
2183                 public void TranslateClip (float dx, float dy) {
2184                         double x = dx;
2185                         double y = dy;
2186                         geom.AffineTransform f = GetFinalTransform();
2187
2188                         if (!f.isIdentity()) {
2189                                 double[] p = new double[] {x, y};
2190                                 f.deltaTransform(p, 0, p, 0, 1);
2191
2192                                 x = p[0];
2193                                 y = p[1];
2194                         }
2195
2196                         // It seems .Net does exactly this...
2197                         x = Math.Floor(x+0.96875);
2198                         y = Math.Floor(y+0.96875);
2199
2200                         geom.AffineTransform t = geom.AffineTransform.getTranslateInstance(x, y);
2201
2202                         _clip.NativeObject.transform(t);
2203                         RestoreBaseClip();
2204                         NativeObject.clip(_clip);
2205                 }
2206                 #endregion
2207
2208                 #region TranslateTransform
2209                 public void TranslateTransform (float dx, float dy) {
2210                         TranslateTransform (dx, dy, MatrixOrder.Prepend);
2211                 }
2212
2213                 
2214                 public void TranslateTransform (float dx, float dy, MatrixOrder order) {
2215                         ConcatenateTransform(
2216                                 geom.AffineTransform.getTranslateInstance(dx, dy), 
2217                                 order);
2218                 }
2219                 #endregion
2220
2221                 #region Properties [Partial TODO]
2222                 public Region Clip {
2223                         get {
2224                                 Region r = _clip.Clone();
2225                                 geom.AffineTransform t = GetFinalTransform();
2226                                 if (!t.isIdentity())
2227                                         r.NativeObject.transform(t.createInverse());
2228
2229                                 return r;
2230                         }
2231                         set {
2232                                 SetClip (value, CombineMode.Replace);
2233                         }
2234                 }
2235
2236                 public RectangleF ClipBounds {
2237                         get {
2238                                 awt.Shape shape = _clip.NativeObject;
2239                                 if (shape == null)
2240                                         shape = Region.InfiniteRegion.NativeObject;
2241
2242                                 geom.RectangularShape r = shape.getBounds2D();
2243                                 geom.AffineTransform t = GetFinalTransform();
2244                                 if (!t.isIdentity()) {
2245                                         geom.AffineTransform it = t.createInverse();
2246                                         r = it.createTransformedShape(r).getBounds2D();
2247                                 }
2248
2249                                 return new RectangleF (r);
2250                         }
2251                 }
2252
2253                 public CompositingMode CompositingMode {
2254                         //TBD:check this carefully
2255                         get {
2256                                 return (NativeObject.getComposite() == awt.AlphaComposite.SrcOver) ?
2257                                         CompositingMode.SourceOver : CompositingMode.SourceCopy;
2258                         }
2259                         set {
2260                                 NativeObject.setComposite(
2261                                         (value == CompositingMode.SourceOver) ?
2262                                         awt.AlphaComposite.SrcOver : awt.AlphaComposite.Src);
2263                         }
2264
2265                 }
2266
2267                 public CompositingQuality CompositingQuality {
2268                         get {
2269                                 awt.RenderingHints hints = NativeObject.getRenderingHints();
2270                                 if(hints.containsKey(awt.RenderingHints.KEY_ALPHA_INTERPOLATION)) {
2271                                         object value_ai = hints.get(awt.RenderingHints.KEY_ALPHA_INTERPOLATION);
2272
2273                                         if (value_ai == awt.RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED)
2274                                                 return CompositingQuality.HighSpeed;
2275                                         if (value_ai == awt.RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY)
2276                                                 return CompositingQuality.HighQuality;
2277                                         if (value_ai == awt.RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT)
2278                                                 return CompositingQuality.Default;
2279                                 }
2280
2281                                 return CompositingQuality.Default;
2282                                         
2283                         }
2284                         set {
2285                                 awt.RenderingHints hints = NativeObject.getRenderingHints();
2286                                 switch (value) {
2287                                         case CompositingQuality.AssumeLinear:
2288                                         case CompositingQuality.Default:
2289                                         case CompositingQuality.GammaCorrected:
2290                                                 hints.put(awt.RenderingHints.KEY_ALPHA_INTERPOLATION,
2291                                                         awt.RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT);
2292                                                 break;
2293                                         case CompositingQuality.HighQuality:
2294                                                 hints.put(awt.RenderingHints.KEY_ALPHA_INTERPOLATION,
2295                                                         awt.RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
2296                                                 break;
2297                                         case CompositingQuality.HighSpeed:
2298                                                 hints.put(awt.RenderingHints.KEY_ALPHA_INTERPOLATION,
2299                                                         awt.RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
2300                                                 break;
2301 //                                      case CompositingQuality.Invalid:
2302 //                                              if(hints.containsKey(awt.RenderingHints.KEY_ALPHA_INTERPOLATION))
2303 //                                                      hints.remove(awt.RenderingHints.KEY_ALPHA_INTERPOLATION);
2304                                 }
2305
2306                                 NativeObject.setRenderingHints(hints);
2307                         }
2308                 }
2309
2310                 public float DpiX {
2311                         get {
2312                                 if (_image != null)
2313                                         return _image.HorizontalResolution;
2314
2315                                 return DefaultScreenResolution;
2316                         }
2317                 }
2318
2319                 public float DpiY {
2320                         get {
2321                                 if (_image != null)
2322                                         return _image.VerticalResolution;
2323
2324                                 return DefaultScreenResolution;
2325                         }
2326                 }
2327
2328                 public InterpolationMode InterpolationMode {
2329                         get {                           
2330                                 awt.RenderingHints hints = NativeObject.getRenderingHints();
2331                                 if(hints.containsKey(awt.RenderingHints.KEY_INTERPOLATION)) {
2332                                         object value_i = hints.get(awt.RenderingHints.KEY_INTERPOLATION);
2333
2334                                         if (value_i == awt.RenderingHints.VALUE_INTERPOLATION_BILINEAR)
2335                                                 return InterpolationMode.Bilinear;
2336                                         if (value_i == awt.RenderingHints.VALUE_INTERPOLATION_BICUBIC)
2337                                                 return InterpolationMode.Bicubic;
2338                                         if (value_i == awt.RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)
2339                                                 return InterpolationMode.NearestNeighbor;
2340                                 }
2341
2342                                 return InterpolationMode.Default;
2343                         }
2344                         set {
2345                                 awt.RenderingHints hints = NativeObject.getRenderingHints();
2346
2347                                 switch (value) {
2348                                         case InterpolationMode.Bicubic:
2349                                         case InterpolationMode.HighQualityBicubic:
2350                                         case InterpolationMode.Low:
2351                                                 hints.put(awt.RenderingHints.KEY_INTERPOLATION, awt.RenderingHints.VALUE_INTERPOLATION_BICUBIC);
2352                                                 break;
2353                                         case InterpolationMode.High:
2354                                         case InterpolationMode.Bilinear:
2355                                         case InterpolationMode.HighQualityBilinear:
2356                                                 hints.put(awt.RenderingHints.KEY_INTERPOLATION, awt.RenderingHints.VALUE_INTERPOLATION_BILINEAR);
2357                                                 break;
2358                                         case InterpolationMode.Default:
2359                                                 if (hints.containsKey(awt.RenderingHints.KEY_INTERPOLATION))
2360                                                         hints.remove(awt.RenderingHints.KEY_INTERPOLATION);
2361                                                 break;
2362                                         case InterpolationMode.NearestNeighbor:
2363                                                 hints.put(awt.RenderingHints.KEY_INTERPOLATION, awt.RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
2364                                                 break;
2365                                         case InterpolationMode.Invalid:
2366                                                 throw new ArgumentException();
2367                                         default:
2368                                                 throw new ArgumentOutOfRangeException();
2369                                 }
2370
2371                                 NativeObject.setRenderingHints(hints);
2372                         }
2373                 }
2374
2375                 public bool IsClipEmpty {
2376                         get {
2377                                 return _clip.IsEmpty(this);
2378                         }
2379                 }
2380
2381                 public bool IsVisibleClipEmpty {
2382                         get {
2383                                 if (_clip.IsEmpty(this))
2384                                         return true;
2385
2386                                 return VisibleClipBounds.IsEmpty;
2387                         }
2388                 }
2389
2390                 public float PageScale {
2391                         get {
2392                                 return _pageScale;
2393                         }
2394                         set {
2395                                 _pageScale = value;
2396                         }
2397                 }
2398
2399                 public GraphicsUnit PageUnit {
2400                         get {
2401                                 return _pageUnit;
2402                         }
2403                         set {
2404                                 _pageUnit = value;
2405                         }
2406                 }
2407
2408                 static internal geom.AffineTransform GetFinalTransform(
2409                         geom.AffineTransform transform, GraphicsUnit pageUnit, float pageScale) {
2410                         geom.AffineTransform t = null;
2411                         if (pageUnit != GraphicsUnit.Display) {
2412                                 float scale = pageScale * _unitConversion[ (int)pageUnit ];
2413                                 if (Math.Abs(scale-1f) > float.Epsilon)
2414                                         t = geom.AffineTransform.getScaleInstance(scale, scale);
2415                         }
2416
2417                         if (t != null)
2418                                 t.concatenate(transform);
2419                         else
2420                                 t = transform;
2421                         
2422                         return t;
2423                 }
2424
2425                 internal geom.AffineTransform GetFinalTransform() {
2426                         return GetFinalTransform(_transform.NativeObject, PageUnit, PageScale);
2427                 }
2428
2429                 public PixelOffsetMode PixelOffsetMode {
2430                         get {
2431                                 return _pixelOffsetMode;
2432                         }
2433                         set {
2434                                 _pixelOffsetMode = value;
2435                         }
2436                 }
2437
2438                 [MonoTODO]
2439                 public Point RenderingOrigin {
2440                         get {
2441                                 throw new NotImplementedException();
2442                         }
2443                         set {
2444                                 throw new NotImplementedException();
2445                         }
2446                 }
2447
2448                 public SmoothingMode SmoothingMode {
2449                         get {
2450                                 awt.RenderingHints hints = NativeObject.getRenderingHints();
2451                                 if(hints.containsKey(awt.RenderingHints.KEY_ANTIALIASING)) {
2452                                         object value_aa = hints.get(awt.RenderingHints.KEY_ANTIALIASING);
2453                                         if (value_aa == awt.RenderingHints.VALUE_ANTIALIAS_ON) {
2454                                                 if(hints.containsKey(awt.RenderingHints.KEY_RENDERING)) {
2455                                                         object value_render = hints.get(awt.RenderingHints.KEY_RENDERING);
2456                                                         if (value_render == awt.RenderingHints.VALUE_RENDER_QUALITY)
2457                                                                 return SmoothingMode.HighQuality;
2458                                                         if (value_render == awt.RenderingHints.VALUE_RENDER_SPEED)
2459                                                                 return SmoothingMode.HighSpeed;
2460                                                 }
2461
2462                                                 return SmoothingMode.AntiAlias;
2463                                         }
2464
2465                                         if (value_aa == awt.RenderingHints.VALUE_ANTIALIAS_DEFAULT)
2466                                                 return SmoothingMode.Default;
2467                                 }
2468                                 return SmoothingMode.None;
2469
2470                         }
2471
2472                         set {
2473                                 awt.RenderingHints hints = NativeObject.getRenderingHints();
2474
2475                                 switch (value) {
2476                                         case SmoothingMode.None:
2477                                                 if(hints.containsKey(awt.RenderingHints.KEY_ANTIALIASING))
2478                                                         hints.remove(awt.RenderingHints.KEY_ANTIALIASING);
2479                                                 if(hints.containsKey(awt.RenderingHints.KEY_RENDERING))
2480                                                         hints.remove(awt.RenderingHints.KEY_RENDERING);
2481                                                 break;
2482                                         case SmoothingMode.AntiAlias:
2483                                                 hints.put(awt.RenderingHints.KEY_ANTIALIASING, awt.RenderingHints.VALUE_ANTIALIAS_ON);
2484                                                 break;
2485                                         case SmoothingMode.HighQuality:
2486                                                 hints.put(awt.RenderingHints.KEY_RENDERING, awt.RenderingHints.VALUE_RENDER_QUALITY);
2487                                                 goto case SmoothingMode.AntiAlias;
2488                                         case SmoothingMode.HighSpeed:
2489                                                 hints.put(awt.RenderingHints.KEY_RENDERING, awt.RenderingHints.VALUE_RENDER_SPEED);
2490                                                 goto case SmoothingMode.None;
2491                                         case SmoothingMode.Default:
2492                                                 hints.put(awt.RenderingHints.KEY_RENDERING, awt.RenderingHints.VALUE_RENDER_DEFAULT);
2493                                                 goto case SmoothingMode.AntiAlias;
2494                                         case SmoothingMode.Invalid:
2495                                                 throw new ArgumentException("Invalid parameter used.");
2496                                 }
2497
2498                                 NativeObject.setRenderingHints(hints);
2499                         }
2500                 }
2501
2502                 /// <summary>
2503                 /// Java does not have similar functionality
2504                 /// </summary>
2505                 public int TextContrast {
2506                         get {
2507                                 return _textContrast;
2508                         }
2509
2510                         set {
2511                                 _textContrast = value;
2512                         }
2513                 }
2514
2515                 public TextRenderingHint TextRenderingHint {
2516                         get {
2517                                 return _textRenderingHint;
2518 //                              awt.RenderingHints hints = NativeObject.getRenderingHints();
2519 //                              if(hints.containsKey(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING)) {
2520 //                                      if(hints.get(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING) == 
2521 //                                              java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON)
2522 //                                              return TextRenderingHint.AntiAlias;
2523 //                                      if(hints.get(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING) == 
2524 //                                              java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)
2525 //                                              return TextRenderingHint.SingleBitPerPixel;
2526 //                              }
2527 //                              //return TextRenderingHint.SystemDefault;
2528 //                              return TextRenderingHint.SingleBitPerPixelGridFit;
2529                         }
2530
2531                         set {
2532                                 _textRenderingHint = value;
2533                                 awt.RenderingHints hints = NativeObject.getRenderingHints();
2534                                 switch (value) {
2535                                         case TextRenderingHint.AntiAlias:
2536                                         case TextRenderingHint.AntiAliasGridFit:
2537                                         case TextRenderingHint.ClearTypeGridFit:
2538 //                                      case TextRenderingHint.SystemDefault:
2539                                                 hints.put(awt.RenderingHints.KEY_TEXT_ANTIALIASING,
2540                                                         awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
2541                                                 break;
2542                                         
2543                                         case TextRenderingHint.SingleBitPerPixelGridFit:
2544                                                 hints.put(awt.RenderingHints.KEY_TEXT_ANTIALIASING,
2545                                                         awt.RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
2546                                                 break;
2547
2548                                         case TextRenderingHint.SingleBitPerPixel:
2549                                                 hints.put(awt.RenderingHints.KEY_TEXT_ANTIALIASING,
2550                                                         awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
2551                                                 break;
2552
2553                                         case TextRenderingHint.SystemDefault:
2554                                                 hints.put(awt.RenderingHints.KEY_TEXT_ANTIALIASING,
2555                                                         awt.RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
2556                                                 break;
2557                                 }
2558                                 
2559                                 NativeObject.setRenderingHints(hints);
2560                         }
2561                 }
2562
2563                 public Matrix Transform {
2564                         get {
2565                                 return _transform.Clone();
2566                         }
2567                         set {
2568                                 if (value == null)
2569                                         throw new ArgumentNullException("matrix");
2570
2571                                 if (!value.IsInvertible)
2572                                         throw new ArgumentException("Invalid parameter used.");
2573
2574                                 value.CopyTo(_transform);
2575                         }
2576                 }
2577
2578                 internal Matrix BaseTransform {
2579                         get {
2580                                 return new Matrix(NativeObject.getTransform());
2581                         }
2582                         set {
2583                                 NativeObject.setTransform(value.NativeObject);
2584                         }
2585                 }
2586
2587                 internal void PrependBaseTransform(geom.AffineTransform t) {
2588                         NativeObject.transform(t);
2589                 }
2590
2591                 internal awt.Shape VisibleShape {
2592                         get {
2593                                 return _windowRect;
2594                         }
2595                 }
2596
2597                 public RectangleF VisibleClipBounds {
2598                         get {
2599                                 if (_clip.IsEmpty(this))
2600                                         return RectangleF.Empty;
2601
2602                                 geom.Rectangle2D r = _clip.NativeObject.getBounds2D();
2603                                 awt.Shape clip = NativeObject.getClip();
2604                                 geom.Rectangle2D clipBounds = (clip != null) ? clip.getBounds2D() : _windowRect;
2605                                 geom.Rectangle2D.intersect(r, clipBounds, r);
2606                                 if ((r.getWidth() <= 0) || (r.getHeight() <= 0))
2607                                         return RectangleF.Empty;
2608
2609                                 geom.AffineTransform t = GetFinalTransform();
2610                                 if (!t.isIdentity()) {
2611                                         geom.AffineTransform it = t.createInverse();
2612                                         r = it.createTransformedShape(r).getBounds2D();
2613                                 }
2614
2615                                 return new RectangleF (r);
2616                         }
2617                 }
2618
2619                 void ConcatenateTransform(geom.AffineTransform transform, MatrixOrder order) {
2620                         geom.AffineTransform at = _transform.NativeObject;
2621                         Matrix.Multiply(at, transform, order);
2622                 }
2623                 #endregion
2624         }
2625 }
2626
2627
2628