* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / System.Drawing / System.Drawing / Graphics.jvm.cs
old mode 100755 (executable)
new mode 100644 (file)
index 4937a46..9597432
@@ -3,6 +3,7 @@ using System.Drawing.Drawing2D;
 using System.Drawing.Imaging;\r
 using System.Drawing.Text;\r
 using System.ComponentModel;\r
+using System.Collections;\r
 using System.Runtime.InteropServices;\r
 using System.Text;\r
 using awt = java.awt;\r
@@ -11,17 +12,173 @@ using geom = java.awt.geom;
 namespace System.Drawing {\r
        [ComVisible(false)]\r
        public sealed class Graphics : MarshalByRefObject, IDisposable {\r
+               sealed class DummyStroke : awt.Stroke {\r
+                       #region Stroke Members\r
+\r
+                       awt.Shape awt.Stroke.createStrokedShape(awt.Shape arg_0) {\r
+                               throw new NotImplementedException("DummyStroke");\r
+                       }\r
+\r
+                       #endregion\r
+               }\r
+\r
+               sealed class NormalizingPathIterator : geom.PathIterator {\r
+\r
+                       #region fields\r
+\r
+                       readonly geom.PathIterator _iter;\r
+\r
+                       const float norm = 0.5f;\r
+                       const float rnd = (1.0f - norm);\r
+                       float ax = 0.0f;\r
+                       float ay = 0.0f;\r
+\r
+                       #endregion\r
+\r
+                       #region ctor\r
+\r
+                       public NormalizingPathIterator(geom.PathIterator iter) {\r
+                               _iter = iter;\r
+                       }\r
+\r
+                       #endregion\r
+\r
+                       #region methods\r
+\r
+                       static int GetIndex(int type) {\r
+                               int index;\r
+                               switch ((GraphicsPath.JPI)type) {\r
+                                       case GraphicsPath.JPI.SEG_CUBICTO:\r
+                                               index = 4;\r
+                                               break;\r
+                                       case GraphicsPath.JPI.SEG_QUADTO:\r
+                                               index = 2;\r
+                                               break;\r
+                                       case GraphicsPath.JPI.SEG_MOVETO:\r
+                                       case GraphicsPath.JPI.SEG_LINETO:\r
+                                               index = 0;\r
+                                               break;\r
+                                       case GraphicsPath.JPI.SEG_CLOSE:\r
+                                       default:\r
+                                               index = -1;\r
+                                               break;\r
+                               }\r
+\r
+                               return index;\r
+                       }\r
+\r
+                       #endregion\r
+\r
+                       #region PathIterator Members\r
+\r
+                       void geom.PathIterator.next() {\r
+                               _iter.next();\r
+                       }\r
+\r
+                       bool geom.PathIterator.isDone() {\r
+                               return _iter.isDone();\r
+                       }\r
+\r
+                       int geom.PathIterator.currentSegment(float[] point) {\r
+                               int type = _iter.currentSegment(point);\r
+\r
+                               int index = GetIndex(type);\r
+                               \r
+                               if (index >= 0) {\r
+                                       float ox = point[index];\r
+                                       float oy = point[index+1];\r
+                                       float newax = (float) java.lang.Math.floor(ox + rnd) + norm;\r
+                                       float neway = (float) java.lang.Math.floor(oy + rnd) + norm;\r
+                                       point[index] = newax;\r
+                                       point[index+1] = neway;\r
+                                       newax -= ox;\r
+                                       neway -= oy;\r
+                                       switch ((GraphicsPath.JPI)type) {\r
+                                               case GraphicsPath.JPI.SEG_CUBICTO:\r
+                                                       point[0] += ax;\r
+                                                       point[1] += ay;\r
+                                                       point[2] += newax;\r
+                                                       point[3] += neway;\r
+                                                       break;\r
+                                               case GraphicsPath.JPI.SEG_QUADTO:\r
+                                                       point[0] += (newax + ax) / 2;\r
+                                                       point[1] += (neway + ay) / 2;\r
+                                                       break;\r
+                                                       //                                                      case GraphicsPath.JPI.SEG_MOVETO:\r
+                                                       //                                                      case GraphicsPath.JPI.SEG_LINETO:\r
+                                                       //                                                      case GraphicsPath.JPI.SEG_CLOSE:\r
+                                                       //                                                              break;\r
+                                       }\r
+                                       ax = newax;\r
+                                       ay = neway;\r
+                               }\r
+\r
+                               return type;\r
+                       }\r
+\r
+                       int geom.PathIterator.currentSegment(double[] point) {\r
+                               int type = _iter.currentSegment(point);\r
+\r
+                               int index = GetIndex(type);\r
+\r
+                               if (index >= 0) {\r
+                                       float ox = (float)point[index];\r
+                                       float oy = (float)point[index+1];\r
+                                       float newax = (float)java.lang.Math.floor(ox + rnd) + norm;\r
+                                       float neway = (float)java.lang.Math.floor(oy + rnd) + norm;\r
+                                       point[index] = newax;\r
+                                       point[index+1] = neway;\r
+                                       newax -= ox;\r
+                                       neway -= oy;\r
+                                       switch ((GraphicsPath.JPI)type) {\r
+                                               case GraphicsPath.JPI.SEG_CUBICTO:\r
+                                                       point[0] += ax;\r
+                                                       point[1] += ay;\r
+                                                       point[2] += newax;\r
+                                                       point[3] += neway;\r
+                                                       break;\r
+                                               case GraphicsPath.JPI.SEG_QUADTO:\r
+                                                       point[0] += (newax + ax) / 2;\r
+                                                       point[1] += (neway + ay) / 2;\r
+                                                       break;\r
+                                                       //                                                      case GraphicsPath.JPI.SEG_MOVETO:\r
+                                                       //                                                      case GraphicsPath.JPI.SEG_LINETO:\r
+                                                       //                                                      case GraphicsPath.JPI.SEG_CLOSE:\r
+                                                       //                                                              break;\r
+                                       }\r
+                                       ax = newax;\r
+                                       ay = neway;\r
+                               }\r
+\r
+                               return type;\r
+                       }\r
+\r
+                       int geom.PathIterator.getWindingRule() {\r
+                               return _iter.getWindingRule();\r
+                       }\r
+\r
+                       #endregion\r
+\r
+               }\r
+\r
+\r
                #region Variables\r
 \r
                readonly awt.Graphics2D _nativeObject;\r
                PixelOffsetMode _pixelOffsetMode = PixelOffsetMode.Default;\r
                int _textContrast = 4;\r
+               TextRenderingHint _textRenderingHint;\r
                readonly Image _image;\r
                \r
-               Matrix _transform;\r
+               readonly Matrix _transform;\r
                GraphicsUnit _pageUnit = GraphicsUnit.Display;\r
                float _pageScale = 1.0f;\r
 \r
+               readonly Region _clip;\r
+               readonly awt.Rectangle _windowRect;\r
+\r
+               GraphicsState _nextGraphicsState = null;\r
+\r
                static readonly float [] _unitConversion = {\r
                                                                                                           1,                                                           // World\r
                                                                                                           1,                                                           // Display\r
@@ -32,7 +189,26 @@ namespace System.Drawing {
                                                                                                           DefaultScreenResolution / 25.4f      // Millimeter\r
                                                                                                   };\r
 \r
-               static internal readonly bool IsHeadless;\r
+               static int _isHeadless;\r
+               static internal bool IsHeadless {\r
+                       get {\r
+                               if (_isHeadless == 0) {\r
+                                       bool isHeadless = awt.GraphicsEnvironment.isHeadless();\r
+                                       if (!isHeadless) {\r
+                                               try {\r
+                                                       awt.Toolkit.getDefaultToolkit();\r
+                                               }\r
+                                               catch{\r
+                                                       isHeadless = true;\r
+                                               }\r
+                                       }\r
+\r
+                                       _isHeadless = isHeadless ? 2 : 1;\r
+                               }\r
+\r
+                               return _isHeadless > 1;\r
+                       }\r
+               }\r
        \r
                #endregion\r
 \r
@@ -49,32 +225,30 @@ namespace System.Drawing {
 \r
                #region Constr. and Destr.\r
                private Graphics (Image image) {\r
-                       _nativeObject = (awt.Graphics2D)image.NativeObject.getGraphics();\r
+                       _nativeObject = (awt.Graphics2D)image.NativeObject.CurrentImage.NativeImage.getGraphics();\r
                        _image = image;\r
                        _transform = new Matrix ();\r
-                       _nativeObject.setTransform( _transform.NativeObject );\r
 \r
+                       NativeObject.setStroke(new DummyStroke());\r
                        NativeObject.setRenderingHint(awt.RenderingHints.KEY_COLOR_RENDERING, awt.RenderingHints.VALUE_COLOR_RENDER_QUALITY);\r
+\r
+                       InterpolationMode = InterpolationMode.Bilinear;\r
+                       TextRenderingHint = TextRenderingHint.SystemDefault;\r
+\r
+                       _windowRect = new awt.Rectangle(_image.Width, _image.Height);\r
+                       _clip = new Region();\r
                }\r
 \r
                #endregion\r
                \r
                #region Internal Accessors\r
 \r
-               static Graphics() {\r
-                       bool isHeadless = awt.GraphicsEnvironment.isHeadless();\r
-                       if (!isHeadless) {\r
-                               try {\r
-                                       awt.Toolkit.getDefaultToolkit();\r
-                               }\r
-                               catch{\r
-                                       isHeadless = true;\r
-                               }\r
+               static internal float [] UnitConversion {\r
+                       get {\r
+                               return _unitConversion;\r
                        }\r
-\r
-                       IsHeadless = isHeadless;\r
                }\r
-\r
+               \r
                static internal int DefaultScreenResolution {\r
                        get {\r
                                return IsHeadless ? 96 :\r
@@ -95,209 +269,144 @@ namespace System.Drawing {
                }\r
                #endregion\r
 \r
-               #region Workers [INTERNAL]\r
-               void InternalSetBrush(Brush b) {\r
-                       java.awt.Graphics2D g = NativeObject;\r
-                       g.setPaint (b);\r
-                       SolidBrush sb = b as SolidBrush;\r
-                       if(sb != null) {\r
-                               g.setColor(sb.Color.NativeObject);\r
-                       }\r
-                       else if(b is LinearGradientBrush) {\r
-#if DEBUG_GRADIENT_BRUSH\r
-                               if(((LinearGradientBrush)b).dPoints != null)\r
-                               {\r
-                                       PointF []pts = ((LinearGradientBrush)b).dPoints;\r
-                                       java.awt.Shape s = g.getClip();\r
-                                       g.setClip(0,0,99999,99999);\r
-                                       g.setPaint(new java.awt.Color(255,0,0));\r
-                                       g.drawLine((int)pts[0].X,(int)pts[0].Y,(int)pts[1].X,(int)pts[1].Y);\r
-                                       g.setPaint(new java.awt.Color(0,255,0));\r
-                                       g.drawLine((int)pts[1].X,(int)pts[1].Y,(int)pts[2].X,(int)pts[2].Y);\r
-                                       g.setPaint(new java.awt.Color(255,0,0));\r
-                                       g.drawLine((int)pts[2].X,(int)pts[2].Y,(int)pts[3].X,(int)pts[3].Y);\r
-                                       g.setPaint(new java.awt.Color(0,255,0));\r
-                                       g.drawLine((int)pts[3].X,(int)pts[3].Y,(int)pts[0].X,(int)pts[0].Y);\r
-                                       \r
-                                       g.setClip(s);\r
-                               }\r
-#endif\r
-                       }\r
-               }\r
 \r
+               #region Workers [INTERNAL]\r
                void DrawShape(Pen pen, awt.Shape shape) {\r
                        if (pen == null)\r
                                throw new ArgumentNullException("pen");\r
 \r
-                       shape = ((awt.Stroke)pen).createStrokedShape(shape);\r
-                       FillShape(pen.Brush, shape);\r
-               }\r
+                       if (StrokeFactory.CanCreateAdvancedStroke && \r
+                               (!pen.CanCreateBasicStroke || !NeedsNormalization)) {\r
+                               geom.AffineTransform oldT = NativeObject.getTransform();\r
+                               NativeObject.setTransform(Matrix.IdentityTransform.NativeObject);\r
 \r
-               void FillShape(awt.Paint paint, awt.Shape shape) {\r
-                       if (paint == null)\r
-                               throw new ArgumentNullException("brush");\r
+                               try {\r
+                                       geom.AffineTransform t = GetFinalTransform();\r
+                                       if (!oldT.isIdentity()) {\r
+                                               t = (geom.AffineTransform)t.clone();\r
+                                               t.preConcatenate(oldT);\r
+                                       }\r
+                                       \r
+                                       double widthsquared = pen.GetSquaredTransformedWidth(t);\r
 \r
-                       awt.Paint old = NativeObject.getPaint();\r
-                       NativeObject.setPaint(paint);\r
-                       try {\r
-                               NativeObject.fill(shape);\r
-                       }\r
-                       finally {\r
-                               NativeObject.setPaint(old);\r
-                       }\r
-               }\r
+                                       bool antiAlias = (SmoothingMode == SmoothingMode.AntiAlias);\r
 \r
-               internal SizeF MeasureDraw (string s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format, bool fDraw) {                    \r
-                       SizeF retVal = new SizeF(0,0);\r
-                       awt.Graphics2D g = NativeObject;\r
-                               \r
-                       java.awt.Font fnt = font.NativeObject;\r
-                       if(s != null && s.Length != 0 && fnt != null) {\r
-                               float size = fnt.getSize();\r
-                               float wid = layoutRectangle.Width;\r
-                               float hei = layoutRectangle.Height;\r
-                               float x = layoutRectangle.X;\r
-                               float y = layoutRectangle.Y;\r
-                               java.text.AttributedString astr = new java.text.AttributedString(s);\r
-                               astr.addAttribute(java.awt.font.TextAttribute.FONT, fnt);\r
-                               java.text.AttributedCharacterIterator prg = astr.getIterator();\r
-                               java.awt.font.TextLayout textlayout = new java.awt.font.TextLayout(prg, g.getFontRenderContext());\r
-                               int prgStart = prg.getBeginIndex();\r
-                               int prgEnd = prg.getEndIndex();\r
-                               java.awt.font.LineBreakMeasurer lineMeasurer = new java.awt.font.LineBreakMeasurer(\r
-                                       prg, new java.awt.font.FontRenderContext(null, false, false));\r
-                               lineMeasurer.setPosition(prgStart);\r
-                               float formatWidth = wid;\r
-                               \r
-                               //some vertical layout magic - should be reviewed\r
-                               //                              if(format != null)\r
-                               //                              {\r
-                               //                                      StringFormatFlags formatflag = format.FormatFlags;\r
-                               //                                      if(formatflag != StringFormatFlags.DirectionVertical)\r
-                               //                                      {\r
-                               //                                              if(size > (float)8 && wid > (float)13)\r
-                               //                                                      formatWidth = wid - (float)12;\r
-                               //                                              if(formatflag ==  StringFormatFlags.DirectionRightToLeft && size == (float)6)\r
-                               //                                                      formatWidth = wid - (float)10;\r
-                               //                                      }\r
-                               //                              }\r
-\r
-                               //now calculate number of lines and full layout height\r
-                               //this is required for LineAlignment calculations....\r
-                               int lines=0;\r
-                               float layHeight=0;\r
-                               float layPrevHeight=0;\r
-                               float layWidth=0;\r
-                               float drawPosY = y;\r
-                               //bool fSkipLastLine = false;\r
-                               java.awt.font.TextLayout layout;\r
-                               java.awt.geom.Rectangle2D bnds = new java.awt.geom.Rectangle2D.Float();\r
-                               while(lineMeasurer.getPosition() < prgEnd) {\r
-                                       layout = lineMeasurer.nextLayout(formatWidth);\r
-                                       lines++;\r
-                                       bnds = bnds.createUnion(layout.getBounds());\r
-                                       layPrevHeight = layHeight;\r
-                                       layHeight += layout.getDescent() + layout.getLeading() + layout.getAscent();\r
-                                       float advance;\r
-                                       if((format != null) && \r
-                                               ((format.FormatFlags & StringFormatFlags.MeasureTrailingSpaces) != 0))\r
-                                               advance = layout.getAdvance();\r
-                                       else\r
-                                               advance = layout.getVisibleAdvance();\r
-                                       if(layWidth < advance)\r
-                                               layWidth = advance;\r
-                                       if((format != null) && ((format.FormatFlags & StringFormatFlags.NoWrap) != 0))\r
-                                               break;\r
-                               }\r
-                               //Overhanging parts of glyphs, and unwrapped text reaching outside \r
-                               //the formatting rectangle are allowed to show. By default all text \r
-                               //and glyph parts reaching outside the formatting rectangle are clipped.\r
-                               if((lines == 1) && \r
-                                       (format != null) && \r
-                                       ((format.FormatFlags & StringFormatFlags.NoClip) != 0)) {\r
-                                       formatWidth = layWidth;                                 \r
-                               }\r
+                                       bool thin = (widthsquared <= (antiAlias ? \r
+                                               AdvancedStroke.MinPenSizeAASquared :\r
+                                               AdvancedStroke.MinPenSizeSquared));\r
 \r
-                               //Only entire lines are laid out in the formatting rectangle. By default layout \r
-                               //continues until the end of the text, or until no more lines are visible as a \r
-                               //result of clipping, whichever comes first. Note that the default settings allow \r
-                               //the last line to be partially obscured by a formatting rectangle that is not a \r
-                               //whole multiple of the line height. To ensure that only whole lines are seen, specify\r
-                               //this value and be careful to provide a formatting rectangle at least as tall as the \r
-                               //height of one line.\r
-                               if(format != null && ((format.FormatFlags & StringFormatFlags.LineLimit) != 0) && \r
-                                       layHeight > hei && layPrevHeight < hei) {\r
-                                       layHeight = layPrevHeight;\r
-                                       lines--;\r
-                               }\r
+                                       PenFit penFit = thin ? (antiAlias ? PenFit.ThinAntiAlias : PenFit.Thin) : PenFit.NotThin;\r
+\r
+                                       if (NeedsNormalization) {\r
 \r
-                               retVal.Height = layHeight;\r
-                               retVal.Width = layWidth+size/2.5f;\r
-                               if(!fDraw)\r
-                                       return retVal;\r
+                                               bool normThin = \r
+                                                       widthsquared <= AdvancedStroke.MinPenSizeSquaredNorm;\r
 \r
-                               InternalSetBrush(brush);\r
+                                               if (normThin) {\r
+                                                       shape = GetNormalizedShape(shape, t);\r
+                                                       shape = pen.GetNativeObject(\r
+                                                               t, null, penFit).createStrokedShape(shape);\r
+                                               }\r
+                                               else {\r
+                                                       shape = pen.GetNativeObject(t, penFit).createStrokedShape(shape);\r
+                                                       shape = GetNormalizedShape(shape, null);\r
+                                               }\r
+                                       }\r
+                                       else {\r
+                                               shape = pen.GetNativeObject(t, penFit).createStrokedShape(shape);\r
+                                       }\r
 \r
-                               //end measurment\r
+                                       FillScaledShape(pen.Brush, shape);\r
+                               }\r
+                               finally {\r
+                                       NativeObject.setTransform(oldT);\r
+                               }\r
+                       }\r
+                       else {\r
+                               awt.Stroke oldStroke = NativeObject.getStroke();\r
+                               NativeObject.setStroke(pen.GetNativeObject(null, PenFit.NotThin));\r
+                               try {\r
 \r
-                               //for draw we should probably update origins\r
+                                       NativeObject.setPaint(pen.Brush);\r
 \r
-                               //Vertical...\r
-                               if(format != null) {\r
-                                       StringAlignment align = format.LineAlignment;\r
-                                       if(align == StringAlignment.Center) {\r
-                                               drawPosY = y + (float)hei/2 - layHeight/2;\r
+                                       geom.AffineTransform oldT = NativeObject.getTransform();\r
+                                       NativeObject.transform(GetFinalTransform());\r
+                                       try {\r
+                                               NativeObject.draw(shape);\r
                                        }\r
-                                       else if(align == StringAlignment.Far) {\r
-                                               drawPosY = (float)y + (float)hei - layHeight;\r
+                                       finally {\r
+                                               NativeObject.setTransform(oldT);\r
                                        }\r
-                                       //in both cases if string is not fit - switch to near\r
-                                       if(drawPosY < y)\r
-                                               drawPosY = y;\r
                                }\r
+                               finally {\r
+                                       NativeObject.setStroke(oldStroke);\r
+                               }\r
+                       }\r
+               }\r
+               void FillShape(Brush paint, awt.Shape shape) {\r
+                       if (paint == null)\r
+                               throw new ArgumentNullException("brush");\r
 \r
-                               //Horisontal... on the fly\r
-                               lineMeasurer.setPosition(prgStart);\r
-                               float drawPosX = x;                             \r
-                               for(int line = 0;line < lines /*lineMeasurer.getPosition() < prgEnd*/;line++, drawPosY += layout.getDescent() + layout.getLeading()) {\r
-                                       layout = lineMeasurer.nextLayout(formatWidth);\r
-                                       drawPosX = x + size / (float)5;//???\r
-                                       drawPosY += layout.getAscent();\r
-                                       if(format != null) {\r
-                                               float advance;\r
-                                               if((format.FormatFlags & StringFormatFlags.MeasureTrailingSpaces) != 0)\r
-                                                       advance = layout.getAdvance();\r
-                                               else\r
-                                                       advance = layout.getVisibleAdvance();\r
-                                               \r
-                                               if(format.Alignment == StringAlignment.Center) {\r
-                                                       drawPosX = (float)((double)x + ((double)formatWidth)/2 - advance/2);\r
-                                               }\r
-                                               else if(format.Alignment == StringAlignment.Far) {\r
-                                                       drawPosX = (float)(drawPosX + formatWidth) - advance;\r
-                                               }\r
-                                               if((format.FormatFlags & StringFormatFlags.DirectionVertical ) != 0) {\r
-                                                       java.awt.geom.AffineTransform at1 = java.awt.geom.AffineTransform.getTranslateInstance(\r
-                                                               drawPosX +  size / (float)5, (drawPosY - layout.getAscent()) + size / (float)5);\r
-\r
-                                                       at1.rotate(Math.PI/2);\r
-                                                       awt.Shape sha = textlayout.getOutline(at1);\r
-                                                       //g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
-                                                       g.fill(sha);\r
-                                                       continue;\r
-                                               }\r
-                                               if((format.FormatFlags & StringFormatFlags.DirectionRightToLeft)  != 0) {\r
-                                                       drawPosX = ((drawPosX + formatWidth) - advance) + (float)9;\r
-                                                       layout.draw(g, drawPosX, drawPosY);\r
-                                               } \r
-                                       }                                       \r
-                                       //Draw current line\r
-                                       layout.draw(g, drawPosX, drawPosY);                                     \r
+                       geom.AffineTransform oldT = null;\r
+                       if (NeedsNormalization) {\r
+                               oldT = NativeObject.getTransform();\r
+                               geom.AffineTransform t = GetFinalTransform();\r
+                               if (!oldT.isIdentity()) {\r
+                                       t = (geom.AffineTransform)t.clone();\r
+                                       t.preConcatenate(oldT);\r
                                }\r
-                       } //not nulls\r
+                               shape = GetNormalizedShape(shape, t);\r
+                       }\r
+                       else {\r
+                               geom.AffineTransform t = GetFinalTransform();\r
+                               if (!t.isIdentity())\r
+                                       shape = t.createTransformedShape(shape);\r
+                       }\r
+\r
+                       if (oldT != null)\r
+                               NativeObject.setTransform(Matrix.IdentityTransform.NativeObject);\r
 \r
-                       return retVal;\r
+                       try {\r
+                               FillScaledShape(paint, shape);\r
+                       }\r
+                       finally {\r
+                               if (oldT != null)\r
+                                       NativeObject.setTransform(oldT);\r
+                       }\r
                }\r
+\r
+               bool NeedsNormalization {\r
+                       get {\r
+                               return PixelOffsetMode != PixelOffsetMode.Half &&\r
+                                       PixelOffsetMode != PixelOffsetMode.HighQuality;\r
+                       }\r
+               }\r
+\r
+               static awt.Shape GetNormalizedShape(awt.Shape shape, geom.AffineTransform t) {\r
+                       geom.PathIterator iter = new NormalizingPathIterator(shape.getPathIterator(t));\r
+       \r
+                       geom.GeneralPath path = new geom.GeneralPath(iter.getWindingRule());\r
+                       path.append(iter, false);\r
+                       return path;\r
+               }\r
+\r
+               void FillScaledShape(Brush paint, awt.Shape shape) {\r
+                       Matrix m = null;\r
+                       if (!(paint is SolidBrush || paint is HatchBrush) && !_transform.IsIdentity) {\r
+                               m = paint.BrushTransform;\r
+                               paint.BrushMultiplyTransform( _transform );\r
+                       }\r
+\r
+                       try {\r
+                               NativeObject.setPaint(paint);\r
+                               NativeObject.fill(shape);\r
+                       }\r
+                       finally {\r
+                               if (m != null)\r
+                                       paint.BrushTransform = m;\r
+                       }\r
+               }\r
+\r
                #endregion\r
 \r
                #region Dispose\r
@@ -308,14 +417,7 @@ namespace System.Drawing {
                \r
                #region Clear\r
                public void Clear (Color color) {\r
-                       geom.AffineTransform old = NativeObject.getTransform();\r
-                       NativeObject.setTransform(new geom.AffineTransform());\r
-                       try {\r
-                               FillShape(color.NativeObject, new awt.Rectangle(0,0,_image.Width,_image.Height));\r
-                       }\r
-                       finally {\r
-                               NativeObject.setTransform(old);\r
-                       }\r
+                       FillScaledShape(new SolidBrush( color ), _clip.NativeObject);\r
                }\r
                #endregion\r
 \r
@@ -482,14 +584,12 @@ namespace System.Drawing {
 \r
                #region DrawImage\r
 \r
-               public void DrawImage (Image image, Point point) \r
-               {\r
-                       DrawImage(image, (int)point.X, (int)point.Y);\r
+               public void DrawImage (Image image, Point point) {\r
+                       DrawImage(image, point.X, point.Y);\r
                }\r
 \r
-               public void DrawImage (Image image, PointF point) \r
-               {\r
-                       DrawImage(image, (int)point.X, (int)point.Y);\r
+               public void DrawImage (Image image, PointF point) {\r
+                       DrawImage(image, point.X, point.Y);\r
                }\r
 \r
                \r
@@ -498,81 +598,56 @@ namespace System.Drawing {
                        DrawImage(image, m);\r
                }\r
 \r
-               public void DrawImage (Image image, PointF [] destPoints) \r
-               {\r
+               public void DrawImage (Image image, PointF [] destPoints) {\r
                        Matrix m = new Matrix(new RectangleF(0, 0, image.Width, image.Height), destPoints);\r
                        DrawImage(image, m);\r
                }\r
 \r
                \r
-               public void DrawImage (Image image, Rectangle rect) \r
-               {\r
+               public void DrawImage (Image image, Rectangle rect) {\r
                        DrawImage(image, rect.X, rect.Y, rect.Width, rect.Height);\r
                }\r
 \r
-               public void DrawImage (Image image, RectangleF rect) \r
-               {\r
-                       DrawImage(image, (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height);\r
+               public void DrawImage (Image image, RectangleF rect) {\r
+                       DrawImage(image, rect.X, rect.Y, rect.Width, rect.Height);\r
                }\r
 \r
                \r
-               public void DrawImage (Image image, int x, int y) \r
-               {\r
-                       float current_scale = PageScale;\r
-                       if (current_scale != 1)\r
-                               PageScale = 1;\r
-\r
-                       try\r
-                       {\r
-                               NativeObject.drawImage(image.NativeObject, x, y, null);\r
-                       }\r
-                       finally\r
-                       {\r
-                               if (current_scale != 1)\r
-                                       PageScale = current_scale;\r
-                       }\r
+               public void DrawImage (Image image, int x, int y) {\r
+                       DrawImage(image, (float)x, (float)y);\r
                }\r
 \r
-               public void DrawImage (Image image, float x, float y) \r
-               {\r
-                       DrawImage(image, (int)x, (int)y);\r
+               public void DrawImage (Image image, float x, float y) {\r
+                       if ((image.HorizontalResolution != DpiX) || (image.VerticalResolution != DpiY))\r
+                               DrawImage( image, x, y, \r
+                                       (float)image.Width * (DpiX / image.HorizontalResolution) / _unitConversion[(int)PageUnit], \r
+                                       (float)image.Height * (DpiY / image.VerticalResolution) / _unitConversion[(int)PageUnit]) ;\r
+                       else\r
+                               DrawImage( image, x, y, \r
+                                       (float)image.Width / _unitConversion[(int)PageUnit], \r
+                                       (float)image.Height / _unitConversion[(int)PageUnit] );\r
                }\r
 \r
                \r
                public void DrawImage (Image image, Rectangle destRect, Rectangle srcRect, GraphicsUnit srcUnit) {\r
-                       if (srcUnit != GraphicsUnit.Pixel)\r
-                               throw new NotImplementedException();\r
-                               // Like in .NET http://dotnet247.com/247reference/msgs/45/227979.aspx\r
-\r
-                       float current_scale = PageScale;\r
-                       if (current_scale != 1)\r
-                               PageScale = 1;\r
-\r
-                       try\r
-                       {\r
-                               NativeObject.drawImage(image.NativeObject,\r
-                                       destRect.X,\r
-                                       destRect.Y,\r
-                                       destRect.X + destRect.Width,\r
-                                       destRect.Y + destRect.Height,\r
-                                       srcRect.X,\r
-                                       srcRect.Y,\r
-                                       srcRect.X + srcRect.Width,\r
-                                       srcRect.Y + srcRect.Height,\r
-                                       null);\r
-                       }\r
-                       finally\r
-                       {\r
-                               if (current_scale != 1)\r
-                                       PageScale = current_scale;\r
-                       }\r
+                       DrawImage(\r
+                               image,\r
+                               new Point [] {\r
+                                                                new Point( destRect.X, destRect.Y),\r
+                                                                new Point( destRect.X + destRect.Width, destRect.Y),\r
+                                                                new Point( destRect.X, destRect.Y + destRect.Height)},\r
+                               srcRect, \r
+                               srcUnit);\r
                }\r
-               \r
+       \r
                public void DrawImage (Image image, RectangleF destRect, RectangleF srcRect, GraphicsUnit srcUnit) {\r
                        DrawImage(\r
-                               image, \r
-                               new Rectangle((int)destRect.X, (int)destRect.Y, (int)destRect.Width, (int)destRect.Height),\r
-                               new Rectangle((int)srcRect.X, (int)srcRect.Y, (int)srcRect.Width, (int)srcRect.Height),\r
+                               image,\r
+                               new PointF [] {\r
+                                                                new PointF( destRect.X, destRect.Y),\r
+                                                                new PointF( destRect.X + destRect.Width, destRect.Y),\r
+                                                                new PointF( destRect.X, destRect.Y + destRect.Height)},\r
+                               srcRect, \r
                                srcUnit);\r
                }\r
 \r
@@ -585,72 +660,43 @@ namespace System.Drawing {
                        DrawImage(image, destPoints, srcRect, srcUnit, null);\r
                }\r
 \r
-               \r
+               [MonoTODO]\r
                public void DrawImage (Image image, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr) {\r
                        //TBD: ImageAttributes\r
                        if (srcUnit != GraphicsUnit.Pixel)\r
                                throw new NotImplementedException();\r
-                               // Like in .NET http://dotnet247.com/247reference/msgs/45/227979.aspx\r
+                       // Like in .NET http://dotnet247.com/247reference/msgs/45/227979.aspx\r
 \r
                        Matrix mx = new Matrix(srcRect, destPoints);\r
 \r
                        Region region = new Region(srcRect);\r
-                       region.Transform (mx);\r
-                       \r
-                       geom.Area current_clip = (geom.Area)GetNativeClip().clone();\r
-                       IntersectClip(region);\r
-                       try\r
-                       {\r
-                               DrawImage(image, mx);\r
-                       }\r
-                       finally\r
-                       {\r
-                               SetNativeClip(current_clip);\r
-                       }\r
+                       DrawImage(image, mx, region);\r
                }\r
                \r
+               [MonoTODO]\r
                public void DrawImage (Image image, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr) {\r
                        //TBD: ImageAttributes\r
                        if (srcUnit != GraphicsUnit.Pixel)\r
                                throw new NotImplementedException();\r
-                               // Like in .NET http://dotnet247.com/247reference/msgs/45/227979.aspx\r
+                       // Like in .NET http://dotnet247.com/247reference/msgs/45/227979.aspx\r
 \r
                        Matrix mx = new Matrix(srcRect, destPoints);\r
 \r
                        Region region = new Region(srcRect);\r
-                       region.Transform (mx);\r
-                       \r
-                       geom.Area current_clip = (geom.Area)GetNativeClip().clone();\r
-                       IntersectClip(region);\r
-                       try\r
-                       {\r
-                               DrawImage(image, mx);\r
-                       }\r
-                       finally\r
-                       {\r
-                               SetNativeClip(current_clip);\r
-                       }\r
+                       DrawImage(image, mx, region);\r
                }\r
 \r
 \r
                public void DrawImage (Image image, int x, int y, int width, int height) {\r
-                       float current_scale = PageScale;\r
-                       if (current_scale != 1)\r
-                               PageScale = 1;\r
-\r
-                       try\r
-                       {\r
-                               NativeObject.drawImage(image.NativeObject, x, y, width, height, null);\r
-                       }\r
-                       finally\r
-                       {\r
-                               if (current_scale != 1)\r
-                                       PageScale = current_scale;\r
-                       }\r
+                       DrawImage(image, (float)x, (float)y, (float)width, (float)height);\r
                }\r
 \r
                public void DrawImage (Image image, float x, float y, float width, float height) {\r
-                       DrawImage(image, (int)x, (int)y, (int)width, (int)height);\r
+                       Matrix mx = new Matrix();\r
+                       mx.Translate((float)x, (float)y);\r
+                       mx.Scale(width / (float)image.Width, height / (float)image.Height);\r
+\r
+                       DrawImage( image, mx );\r
                }\r
 \r
                \r
@@ -672,6 +718,7 @@ namespace System.Drawing {
                }\r
                \r
 \r
+               [MonoTODO]\r
                public void DrawImage (Image image, Rectangle destRect, int srcX, int srcY, int srcWidth, int srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttr) {                     \r
                        //TBD: attributes\r
                        DrawImage(\r
@@ -681,47 +728,101 @@ namespace System.Drawing {
                                srcUnit);\r
                }\r
                \r
+               [MonoTODO]\r
                public void DrawImage (Image image, Rectangle destRect, float srcX, float srcY, float srcWidth, float srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttrs) {\r
                        //TBD: attributes\r
                        DrawImage(\r
                                image, \r
                                destRect,\r
-                               new Rectangle((int)srcX, (int)srcY, (int)srcWidth, (int)srcHeight),\r
+                               new RectangleF(srcX, srcY, srcWidth, srcHeight),\r
                                srcUnit);\r
                }\r
                \r
 \r
                internal void DrawImage (Image image, Matrix m) {\r
-                       float current_scale = PageScale;\r
-                       if (current_scale != 1)\r
-                               PageScale = 1;\r
+                       DrawImage(image, m, null);\r
+               }\r
+\r
+               internal void DrawImage (Image image, Matrix m, Region clip) {\r
+                       if (clip == null) {\r
+                               clip = new Region( new RectangleF( 0, 0, image.Width, image.Height ) );\r
+                       }\r
+\r
+                       geom.AffineTransform t = GetFinalTransform(_transform.NativeObject, PageUnit, 1.0f);\r
+                       if (!t.isIdentity())\r
+                               m.NativeObject.preConcatenate(t);\r
+\r
+                               clip.Transform( m );\r
 \r
-                       try\r
-                       {\r
-                               NativeObject.drawImage(image.NativeObject, m.NativeObject, null);\r
+                       if (NeedsNormalization) {\r
+                               Matrix normMatrix = ComputeClipNormalization(clip.GetBounds(this));\r
+                               clip.Transform(normMatrix);\r
                        }\r
-                       finally\r
-                       {\r
-                               if (current_scale != 1)\r
-                                       PageScale = current_scale;\r
+\r
+                       awt.Shape oldClip = NativeObject.getClip();\r
+                       IntersectScaledClipWithBase(clip);\r
+                       \r
+                       try {\r
+                               Matrix mm = ComputeImageNormalization(image, m);\r
+                               NativeObject.drawImage(image.NativeObject.CurrentImage.NativeImage, mm.NativeObject, null);\r
+                       }\r
+                       finally {\r
+                               NativeObject.setClip( oldClip );\r
                        }\r
                }\r
+\r
+               private static Matrix ComputeImageNormalization(Image img, Matrix m) {\r
+                       if ( m.IsIdentity )\r
+                               return m;\r
+\r
+                       //m.Translate( -(m.Elements[0] + m.Elements[2]) / 2.0f,  -(m.Elements[3] + m.Elements[1]) / 2.0f, MatrixOrder.Append);\r
+                       m.Translate( \r
+                               -(float)(m.NativeObject.getScaleX() + m.NativeObject.getShearX()) / 2.0f,  \r
+                               -(float)(m.NativeObject.getScaleY() + m.NativeObject.getShearY()) / 2.0f, MatrixOrder.Append);\r
+                       \r
+                       PointF [] p = new PointF[] { \r
+                                                                                  new PointF( 0, 0 ),\r
+                                                                                  new PointF( img.Width, 0 ),\r
+                                                                                  new PointF( 0, img.Height )};\r
+\r
+                       m.TransformPoints(p);\r
+                       for (int i=0; i < p.Length; i++) {\r
+                               p[i].X = (float)( p[i].X + 0.5f );\r
+                               p[i].Y = (float)( p[i].Y + 0.5f );\r
+                       }\r
+\r
+                       return new Matrix( new Rectangle(0, 0, img.Width, img.Height), p );\r
+               }\r
+               private static Matrix ComputeClipNormalization(RectangleF rect) {\r
+                       PointF [] p = new PointF[] { \r
+                                                                                  new PointF( rect.X, rect.Y ),\r
+                                                                                  new PointF( rect.X + rect.Width, rect.Y ),\r
+                                                                                  new PointF( rect.X, rect.Y + rect.Height )};\r
+\r
+                       for (int i=0; i < p.Length; i++) {\r
+                               p[i].X = (float)Math.Round( p[i].X + 0.5f ) + 0.5f;\r
+                               p[i].Y = (float)Math.Round( p[i].Y + 0.5f ) + 0.5f;\r
+                       }\r
+\r
+                       return new Matrix( rect, p );\r
+               }\r
                \r
 \r
 #if INTPTR_SUPPORT\r
+               [MonoTODO]\r
                public void DrawImage (Image image, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback)\r
                {\r
                        throw new NotImplementedException();\r
                }\r
 \r
-               \r
+               [MonoTODO]\r
                public void DrawImage (Image image, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback)\r
                {\r
                        \r
                        throw new NotImplementedException();\r
                }\r
 \r
-               \r
+               [MonoTODO]\r
                public void DrawImage (Image image, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback, int callbackData)\r
                {\r
                        throw new NotImplementedException();\r
@@ -729,6 +830,7 @@ namespace System.Drawing {
 #endif\r
 \r
 #if INTPTR_SUPPORT             \r
+               [MonoTODO]\r
                public void DrawImage (Image image, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback, int callbackData)\r
                {\r
                        throw new NotImplementedException();\r
@@ -912,250 +1014,401 @@ namespace System.Drawing {
 \r
                #region DrawString\r
                public void DrawString (string s, Font font, Brush brush, RectangleF layoutRectangle) {                 \r
-                       MeasureDraw(s,font,brush,layoutRectangle,null,true);\r
+                       DrawString(s, font, brush, layoutRectangle.X, layoutRectangle.Y, layoutRectangle.Width, layoutRectangle.Height, null);\r
                }\r
                \r
                public void DrawString (string s, Font font, Brush brush, PointF point) {\r
-                       MeasureDraw(s,font,brush,new RectangleF(point.X,point.Y,99999f,99999f),null,true);\r
+                       DrawString(s, font, brush, point.X, point.Y, float.PositiveInfinity, float.PositiveInfinity, null);\r
                }\r
                \r
                public void DrawString (string s, Font font, Brush brush, PointF point, StringFormat format) {\r
-                       MeasureDraw(s,font,brush,new RectangleF(point.X,point.Y,99999f,99999f),format,true);\r
+                       DrawString(s, font, brush, point.X, point.Y, float.PositiveInfinity, float.PositiveInfinity, format);\r
                }\r
 \r
                public void DrawString (string s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format) {\r
-                       MeasureDraw(s,font,brush,layoutRectangle,format,true);\r
-               }\r
-       \r
-#if false              \r
-               public void DrawString (string s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format)\r
-               {\r
-                       java.awt.Graphics2D g = (java.awt.Graphics2D)nativeObject;                      \r
-                       //set\r
-                       java.awt.Paint oldpaint = g.getPaint();\r
-                       g.setPaint(brush.NativeObject);\r
-                       java.awt.Font oldfont = g.getFont();\r
-                       g.setFont(font.NativeObject);\r
-                       java.awt.Shape oldb = g.getClip();\r
-                       g.setClip(new java.awt.geom.Rectangle2D.Float(layoutRectangle.X,layoutRectangle.Y,layoutRectangle.Width,layoutRectangle.Height));\r
-                       //draw\r
-                       g.drawString(s,layoutRectangle.X,layoutRectangle.Y+layoutRectangle.Height);\r
-                       //restore\r
-                       g.setPaint(oldpaint);\r
-                       g.setClip(oldb);\r
-                       g.setFont(oldfont);\r
+                       DrawString(s, font, brush, layoutRectangle.X, layoutRectangle.Y, layoutRectangle.Width, layoutRectangle.Height, format);\r
                }\r
-#endif\r
+\r
                public void DrawString (string s, Font font, Brush brush, float x, float y) {\r
-                       MeasureDraw(s,font,brush,new RectangleF(x,y,99999f,99999f),null,true);\r
+                       DrawString(s, font, brush, x, y, float.PositiveInfinity, float.PositiveInfinity, null);\r
                }\r
 \r
                public void DrawString (string s, Font font, Brush brush, float x, float y, StringFormat format) {\r
-                       MeasureDraw(s,font,brush,new RectangleF(x,y,99999f,99999f),format,true);\r
+                       DrawString(s, font, brush, x, y, float.PositiveInfinity, float.PositiveInfinity, format);\r
+               }\r
+\r
+               void DrawString (string s, Font font, Brush brush, \r
+                       float x, float y, float width, float height, \r
+                       StringFormat format) {\r
+                       if (brush == null)\r
+                               throw new ArgumentNullException("brush");\r
+\r
+                       if (font == null)\r
+                               throw new ArgumentNullException("font");\r
+\r
+                       if (format != null && format.LineAlignment != StringAlignment.Near) {\r
+\r
+                               SizeF sizeF = MeasureString(s, font, format, width, height, null);\r
+\r
+                               float lineAWidth = width;\r
+                               float lineAHeight = height;\r
+\r
+                               if (float.IsPositiveInfinity(width))\r
+                                       lineAWidth = lineAHeight = 0;\r
+\r
+                               float wdelta = format.IsVertical ? lineAWidth - sizeF.Width : lineAHeight - sizeF.Height;\r
+                               float pdelta = format.LineAlignment == StringAlignment.Center ? wdelta/2 : wdelta;\r
+                               if (format.IsVertical) {\r
+                                       if (!(format.IsRightToLeft && format.LineAlignment == StringAlignment.Far))\r
+                                               x += pdelta;\r
+                                       if (!float.IsPositiveInfinity(width))\r
+                                               width -= wdelta;\r
+                               }\r
+                               else {\r
+                                       y += pdelta;\r
+                                       if (!float.IsPositiveInfinity(width))\r
+                                               height -= wdelta;\r
+                               }\r
+                       }\r
+\r
+                       awt.Paint oldP = NativeObject.getPaint();\r
+                       NativeObject.setPaint(brush);\r
+                       try {\r
+                               geom.AffineTransform oldT = NativeObject.getTransform();\r
+                               NativeObject.transform(GetFinalTransform());\r
+                               try {\r
+\r
+                                       bool noclip = float.IsPositiveInfinity(width) || (format != null && format.NoClip);\r
+\r
+                                       awt.Shape oldClip = null;\r
+                                       if (!noclip) {\r
+                                               oldClip = NativeObject.getClip();\r
+                                               NativeObject.clip(new geom.Rectangle2D.Float(x, y, width, height));\r
+                                       }\r
+                                       try {\r
+                                               TextLineIterator iter = new TextLineIterator(s, font, NativeObject.getFontRenderContext(), format, width, height);\r
+                                               NativeObject.transform(iter.Transform);\r
+                                               for (LineLayout layout = iter.NextLine(); layout != null; layout = iter.NextLine()) {\r
+                                                       layout.Draw(NativeObject, x, y);\r
+                                               }\r
+                                       }\r
+                                       finally {\r
+                                               if (!noclip)\r
+                                                       NativeObject.setClip(oldClip);\r
+                                       }\r
+                               }\r
+                               finally {\r
+                                       NativeObject.setTransform(oldT);\r
+                               }\r
+                       }\r
+                       finally {\r
+                               NativeObject.setPaint(oldP);\r
+                       }\r
                }\r
                #endregion\r
 \r
-               #region Container [TODO]\r
+               #region Container\r
+\r
+               void PushGraphicsState(GraphicsState state) {\r
+                       state.Next = _nextGraphicsState;\r
+                       _nextGraphicsState = state;\r
+               }\r
+\r
+               GraphicsState PopGraphicsState() {\r
+                       GraphicsState state = _nextGraphicsState;\r
+                       _nextGraphicsState = _nextGraphicsState.Next;\r
+                       return state;\r
+               }\r
+\r
+               bool ContainsGraphicsState(GraphicsState state) {\r
+                       GraphicsState gs = _nextGraphicsState;\r
+\r
+                       while(gs != null) {\r
+                               if (gs == state)\r
+                                       return true;\r
+\r
+                               gs = gs.Next;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
                public void EndContainer (GraphicsContainer container) {\r
-                       throw new NotImplementedException ();\r
+                       Restore(container.StateObject);\r
                }\r
 \r
                public GraphicsContainer BeginContainer () {\r
-                       throw new NotImplementedException ();\r
+                       return new GraphicsContainer(Save(Matrix.IdentityTransform, true));\r
                }\r
                \r
                public GraphicsContainer BeginContainer (Rectangle dstrect, Rectangle srcrect, GraphicsUnit unit) {\r
-                       throw new NotImplementedException ();\r
+                       Matrix containerTransfrom =\r
+                               new Matrix(     srcrect,\r
+                               new Point [] {   new Point (dstrect.X, dstrect.Y), \r
+                                                                new Point (dstrect.X + dstrect.Width, dstrect.Y), \r
+                                                                new Point (dstrect.X, dstrect.Y + dstrect.Height) });\r
+\r
+                       float scale = _unitConversion[ (int)PageUnit ] / _unitConversion[ (int)unit ];\r
+                       containerTransfrom.Scale(scale, scale);\r
+\r
+                       return new GraphicsContainer(Save(containerTransfrom, true));\r
                }\r
 \r
                \r
                public GraphicsContainer BeginContainer (RectangleF dstrect, RectangleF srcrect, GraphicsUnit unit) {\r
-                       throw new NotImplementedException ();\r
+                       Matrix containerTransfrom =\r
+                               new Matrix(     srcrect,\r
+                               new PointF [] {  new PointF (dstrect.X, dstrect.Y), \r
+                                                                new PointF (dstrect.X + dstrect.Width, dstrect.Y), \r
+                                                                new PointF (dstrect.X, dstrect.Y + dstrect.Height) });\r
+\r
+                       float scale = _unitConversion[ (int)PageUnit ] / _unitConversion[ (int)unit ];\r
+                       containerTransfrom.Scale(scale, scale);\r
+\r
+                       return new GraphicsContainer(Save(containerTransfrom, true));\r
+               }\r
+\r
+               GraphicsState Save(Matrix matrix, bool resetState) {\r
+                       GraphicsState graphicsState = new GraphicsState(this, matrix, resetState);\r
+\r
+                       PushGraphicsState( graphicsState );\r
+                       return graphicsState;\r
+               }\r
+\r
+               public GraphicsState Save () {\r
+                       return Save(Matrix.IdentityTransform, false);\r
+               }\r
+\r
+               public void Restore (GraphicsState graphicsState) {\r
+                       if (ContainsGraphicsState(graphicsState)) {\r
+                               GraphicsState gs = PopGraphicsState();\r
+                               while ( gs != graphicsState )\r
+                                       gs = PopGraphicsState();\r
+\r
+                               graphicsState.RestoreState(this);\r
+                       }\r
                }\r
 \r
                #endregion\r
 \r
-               #region Metafiles Staff [TODO NotSupp]\r
+               #region Metafiles Staff\r
+               [MonoTODO]\r
                public void AddMetafileComment (byte [] data) {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
 #if INTPTR_SUPPORT\r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Point [] destPoints, EnumerateMetafileProc callback)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, RectangleF destRect, EnumerateMetafileProc callback)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, EnumerateMetafileProc callback)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Rectangle destRect, EnumerateMetafileProc callback)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Point destPoint, EnumerateMetafileProc callback)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, PointF destPoint, EnumerateMetafileProc callback)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, PointF destPoint, EnumerateMetafileProc callback, IntPtr callbackData)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Rectangle destRect, EnumerateMetafileProc callback, IntPtr callbackData)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, EnumerateMetafileProc callback, IntPtr callbackData)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Point destPoint, EnumerateMetafileProc callback, IntPtr callbackData)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Point [] destPoints, EnumerateMetafileProc callback, IntPtr callbackData)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, RectangleF destRect, EnumerateMetafileProc callback, IntPtr callbackData)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, PointF destPoint, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Point destPoint, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, RectangleF destRect, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Rectangle destRect, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, RectangleF destRect, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Point destPoint, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, PointF destPoint, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Point [] destPoints, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Rectangle destRect, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Rectangle destRect, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, RectangleF destRect, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, PointF destPoint, RectangleF srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Point destPoint, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Point [] destPoints, Rectangle srcRect, GraphicsUnit srcUnit, EnumerateMetafileProc callback, IntPtr callbackData)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Point [] destPoints, Rectangle srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Rectangle destRect, Rectangle srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, Point destPoint, Rectangle srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, RectangleF destRect, RectangleF srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, PointF [] destPoints, RectangleF srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                public void EnumerateMetafile (Metafile metafile, PointF destPoint, RectangleF srcRect, GraphicsUnit unit, EnumerateMetafileProc callback, IntPtr callbackData, ImageAttributes imageAttr)\r
                {\r
                        throw new NotImplementedException ();\r
@@ -1164,16 +1417,27 @@ namespace System.Drawing {
                #endregion      \r
 \r
                #region ExcludeClip\r
+               void ExcludeClip(geom.Area area) {\r
+\r
+                       geom.AffineTransform t = GetFinalTransform();\r
+                       if (!t.isIdentity()) {\r
+                               area = (geom.Area)area.clone();\r
+                               area.transform(t);\r
+                       }\r
+\r
+                       _clip.NativeObject.subtract(area);\r
+                       RestoreBaseClip();\r
+                       NativeObject.clip(_clip);\r
+               }\r
+\r
                public void ExcludeClip (Rectangle rect) {\r
-                       geom.Area clip = GetNativeClip();\r
-                       clip.subtract(new geom.Area(rect.NativeObject));\r
-                       SetNativeClip(clip);\r
+                       ExcludeClip(new geom.Area(rect.NativeObject));\r
                }\r
 \r
                public void ExcludeClip (Region region) {\r
-                       geom.Area clip = GetNativeClip();\r
-                       clip.subtract(region.NativeObject);\r
-                       SetNativeClip(clip);\r
+                       if (region == null)\r
+                               throw new ArgumentNullException("region");\r
+                       ExcludeClip(region.NativeObject);\r
                }\r
                #endregion \r
 \r
@@ -1229,6 +1493,9 @@ namespace System.Drawing {
 \r
                #region FillPath\r
                public void FillPath (Brush brush, GraphicsPath path) {\r
+                       if (path == null)\r
+                               throw new ArgumentNullException("path");\r
+\r
                        FillShape(brush,path);\r
                }\r
                #endregion\r
@@ -1315,70 +1582,81 @@ namespace System.Drawing {
                \r
                public void Flush (FlushIntention intention) {\r
                        if (_image != null)\r
-                               _image.NativeObject.flush();\r
+                               _image.NativeObject.CurrentImage.NativeImage.flush();\r
                }\r
 \r
 #if INTPTR_SUPPORTED\r
                [EditorBrowsable (EditorBrowsableState.Advanced)]\r
+               [MonoTODO]\r
                public void ReleaseHdc (IntPtr hdc)\r
                {\r
                        throw new NotImplementedException();\r
                }\r
 \r
                [EditorBrowsable (EditorBrowsableState.Advanced)]\r
+               [MonoTODO]\r
                public void ReleaseHdcInternal (IntPtr hdc)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
                [EditorBrowsable (EditorBrowsableState.Advanced)]               \r
+               [MonoTODO]\r
                public static Graphics FromHdc (IntPtr hdc)\r
                {\r
                        throw new NotImplementedException();\r
                }\r
 \r
                [EditorBrowsable (EditorBrowsableState.Advanced)]\r
+               [MonoTODO]\r
                public static Graphics FromHdc (IntPtr hdc, IntPtr hdevice)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
                [EditorBrowsable (EditorBrowsableState.Advanced)]\r
+               [MonoTODO]\r
                public static Graphics FromHdcInternal (IntPtr hdc)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
                [EditorBrowsable (EditorBrowsableState.Advanced)]               \r
+               [MonoTODO]\r
                public static Graphics FromHwnd (IntPtr hwnd)\r
                {\r
                        throw new NotImplementedException();\r
                }\r
 \r
                [EditorBrowsable (EditorBrowsableState.Advanced)]\r
+               [MonoTODO]\r
                public static Graphics FromHwndInternal (IntPtr hwnd)\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
+               [MonoTODO]\r
                internal static Graphics FromXDrawable (IntPtr drawable, IntPtr display)\r
                {\r
                        throw new NotImplementedException();\r
                }\r
 \r
+               [MonoTODO]\r
                public static IntPtr GetHalftonePalette ()\r
                {\r
                        throw new NotImplementedException ();\r
                }\r
 \r
                [EditorBrowsable (EditorBrowsableState.Advanced)]\r
+               [MonoTODO]\r
                public IntPtr GetHdc ()\r
                {\r
                        throw new NotImplementedException();\r
                }\r
 #endif\r
                \r
-               #region GetNearestColor [TODO]\r
+               #region GetNearestColor\r
+               [MonoTODO]\r
                public Color GetNearestColor (Color color) {\r
                        throw new NotImplementedException();\r
                }\r
@@ -1386,9 +1664,16 @@ namespace System.Drawing {
 \r
                #region IntersectClip\r
                void IntersectClip (geom.Area area) {\r
-                       geom.Area clip = GetNativeClip();\r
-                       clip.intersect(area);\r
-                       SetNativeClip(clip);\r
+                       \r
+                       geom.AffineTransform t = GetFinalTransform();\r
+                       if (!t.isIdentity()) {\r
+                               area = (geom.Area)area.clone();\r
+                               area.transform(t);\r
+                       }\r
+\r
+                       _clip.NativeObject.intersect(area);\r
+                       RestoreBaseClip();\r
+                       NativeObject.clip(_clip);\r
                }\r
 \r
                public void IntersectClip (Region region) {\r
@@ -1426,12 +1711,24 @@ namespace System.Drawing {
                }\r
                \r
                public bool IsVisible (float x, float y) {\r
-                       java.awt.Graphics2D g = NativeObject;\r
-                       java.awt.Shape s = g.getClip();\r
-                       if (s == null)\r
+                       double dx = x;\r
+                       double dy = y;\r
+                       geom.AffineTransform t = GetFinalTransform();\r
+                       if (!t.isIdentity()) {\r
+                               double[] p = new double[] {dx, dy};\r
+                               t.transform(p, 0, p, 0, 1);\r
+\r
+                               dx = p[0];\r
+                               dy = p[1];\r
+                       }\r
+                       if (!_clip.NativeObject.contains(dx, dy))\r
+                               return false;\r
+\r
+                       awt.Shape clip = NativeObject.getClip();\r
+                       if (clip == null)\r
                                return true;\r
-                       else                            \r
-                               return s.contains(x,y);\r
+\r
+                       return clip.contains(dx, dy);\r
                }\r
                \r
                public bool IsVisible (int x, int y) {\r
@@ -1439,12 +1736,17 @@ namespace System.Drawing {
                }\r
                \r
                public bool IsVisible (float x, float y, float width, float height) {\r
-                       java.awt.Graphics2D g = NativeObject;\r
-                       java.awt.Shape s = g.getClip();\r
-                       if (s == null)\r
-                               return true;\r
-                       else                            \r
-                               return s.contains(x,y,width,height);\r
+\r
+                       geom.AffineTransform t = GetFinalTransform();\r
+                       geom.Rectangle2D r = new geom.Rectangle2D.Float(x, y, width, height);\r
+                       \r
+                       if (!t.isIdentity())\r
+                               r = t.createTransformedShape(r).getBounds2D();\r
+               \r
+                       return NativeObject.hitClip(\r
+                                       (int)(r.getX()+0.5), (int)(r.getY()+0.5),\r
+                                       (int)(r.getWidth()+0.5), (int)(r.getHeight()+0.5))\r
+                               && _clip.NativeObject.intersects(r);\r
                }\r
 \r
                \r
@@ -1453,47 +1755,178 @@ namespace System.Drawing {
                }\r
                #endregion\r
 \r
-               #region MeasureCharacterRanges [TODO]\r
+               #region MeasureCharacterRanges\r
                public Region [] MeasureCharacterRanges (string text, Font font, RectangleF layoutRect, StringFormat stringFormat) {\r
-                       throw new NotImplementedException();\r
+                       if (stringFormat == null)\r
+                               throw new ArgumentException("stringFormat");\r
+\r
+                       CharacterRange[] ranges = stringFormat.CharRanges;\r
+                       if (ranges == null || ranges.Length == 0)\r
+                               return new Region[0];\r
+\r
+                       GraphicsPath[] pathes = new GraphicsPath[ranges.Length];\r
+                       for (int i = 0; i < pathes.Length; i++)\r
+                               pathes[i] = new GraphicsPath();\r
+\r
+                       TextLineIterator iter = new TextLineIterator(text, font, NativeObject.getFontRenderContext(),\r
+                               stringFormat, layoutRect.Width, layoutRect.Height);\r
+                       \r
+                       for (LineLayout layout = iter.NextLine(); layout != null; layout = iter.NextLine()) {\r
+\r
+                               for (int i = 0; i < ranges.Length; i++) {\r
+                                       int start = ranges[i].First;\r
+                                       int length = ranges[i].Length;\r
+                                       start -= iter.CharsConsumed;\r
+                                       int limit = start + length;\r
+                                       int layoutStart = iter.CurrentPosition - layout.CharacterCount;\r
+                                       if (start < iter.CurrentPosition && limit > layoutStart) {\r
+\r
+                                               float layoutOffset;\r
+                                               if (start > layoutStart)\r
+                                                       layoutOffset = iter.GetAdvanceBetween(layoutStart, start);\r
+                                               else {\r
+                                                       layoutOffset = 0;\r
+                                                       start = layoutStart;\r
+                                               }\r
+\r
+                                               float width = (limit < iter.CurrentPosition) ?\r
+                                                       iter.GetAdvanceBetween(start, limit) :\r
+                                                       layout.Width - layoutOffset;\r
+\r
+                                               float height = layout.Ascent + layout.Descent;\r
+\r
+                                               float x = layout.NativeX;\r
+                                               float y = layout.NativeY;\r
+\r
+                                               if (stringFormat.IsVertical) {\r
+                                                       y += layoutOffset;\r
+                                                       x -= layout.Descent;\r
+                                               }\r
+                                               else {\r
+                                                       x += layoutOffset;\r
+                                                       y -= layout.Ascent;\r
+                                               }\r
+\r
+                                               if (layout.AccumulatedHeight + height > iter.WrapHeight) {\r
+                                                       float diff = iter.WrapHeight - layout.AccumulatedHeight;\r
+                                                       if (stringFormat.IsVertical && stringFormat.IsRightToLeft) {\r
+                                                               x += diff;\r
+                                                               height -= diff;\r
+                                                       }\r
+                                                       else\r
+                                                               height = diff;\r
+                                               }\r
+\r
+                                               if (stringFormat.IsVertical)\r
+                                                       pathes[i].AddRectangle(x + layoutRect.X, y + layoutRect.Y, height, width);\r
+                                               else\r
+                                                       pathes[i].AddRectangle(x + layoutRect.X, y + layoutRect.Y, width, height);\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       geom.AffineTransform lineAlignT = iter.CalcLineAlignmentTransform();\r
+                       if (lineAlignT != null) {\r
+                               for (int i = 0; i < pathes.Length; i++)\r
+                                       pathes[i].NativeObject.transform(lineAlignT);\r
+                       }\r
+\r
+                       Region[] regions = new Region[ranges.Length];\r
+                       for (int i = 0; i < regions.Length; i++)\r
+                               regions[i] = new Region(pathes[i]);\r
+\r
+                       return regions;\r
                }\r
                #endregion\r
                \r
-               #region MeasureString [1 method still TODO]\r
+               #region MeasureString\r
                public SizeF MeasureString (string text, Font font) {\r
-                       return MeasureDraw(text,font,null,new RectangleF(0,0,99999f,99999f),null,false);\r
+                       return MeasureString(text, font, null, float.PositiveInfinity, float.PositiveInfinity, null); \r
                }\r
 \r
                \r
                public SizeF MeasureString (string text, Font font, SizeF layoutArea) {\r
-                       return MeasureDraw(text,font,null,new RectangleF(0,0,layoutArea.Width,layoutArea.Height),null,false);\r
+                       return MeasureString(text, font, layoutArea, null);\r
                }\r
 \r
                \r
                public SizeF MeasureString (string text, Font font, int width) {\r
-                       return MeasureDraw(text,font,null,new RectangleF(0,0,(float)width,99999f),null,false);\r
+                       return MeasureString(text, font, width, null);\r
                }\r
 \r
 \r
                public SizeF MeasureString (string text, Font font, SizeF layoutArea, StringFormat format) {\r
-                       return MeasureDraw(text,font,null,new RectangleF(0,0,layoutArea.Width,layoutArea.Height),format,false);\r
+                       return MeasureString(text, font, format, layoutArea.Width, layoutArea.Height, null);\r
                }\r
 \r
                \r
                public SizeF MeasureString (string text, Font font, int width, StringFormat format) {\r
-                       return MeasureDraw(text,font,null,new RectangleF(0,0,(float)width,99999f),format,false);\r
+                       return MeasureString(text, font, format, width, float.PositiveInfinity, null);\r
                }\r
 \r
                \r
                public SizeF MeasureString (string text, Font font, PointF origin, StringFormat format) {\r
-                       //TBD: MeasureDraw still not dealing with clipping region of dc\r
-                       return MeasureDraw(text,font,null,new RectangleF(origin.X,origin.Y,99999f,99999f),format,false);\r
+                       return MeasureString(text, font, format, float.PositiveInfinity, float.PositiveInfinity, null);\r
+               }\r
+\r
+               SizeF MeasureString (string text, Font font, StringFormat format, float width, float height, int[] statistics) {\r
+\r
+                       if (statistics != null) {\r
+                               statistics[0] = 0;\r
+                               statistics[1] = 0;\r
+                       }\r
+\r
+                       TextLineIterator iter = new TextLineIterator(text, font, NativeObject.getFontRenderContext(), format, width, height);\r
+\r
+                       float mwidth = 0;\r
+                       int linesFilled = 0;\r
+                       for (LineLayout layout = iter.NextLine(); layout != null; layout = iter.NextLine()) {\r
+\r
+                               linesFilled ++;\r
+                               float w = layout.MeasureWidth;\r
+\r
+                               if (w > mwidth)\r
+                                       mwidth = w;\r
+                       }\r
+\r
+                       if (linesFilled == 0)\r
+                               return SizeF.Empty;\r
+\r
+                       float mheight = iter.AccumulatedHeight;\r
+\r
+                       if (format != null) {\r
+                               if (format.IsVertical) {\r
+                                       float temp = mheight;\r
+                                       mheight = mwidth;\r
+                                       mwidth = temp;\r
+                               }\r
+                       }\r
+\r
+                       if (!(format != null && format.NoClip)) {\r
+                               if (mwidth > width)\r
+                                       mwidth = width;\r
+                               if (mheight > height)\r
+                                       mheight = height;\r
+                       }\r
+\r
+                       if (statistics != null) {\r
+                               statistics[0] = linesFilled;\r
+                               statistics[1] = iter.CharsConsumed;\r
+                       }\r
+\r
+                       return new SizeF(mwidth, mheight);\r
                }\r
 \r
                \r
                public SizeF MeasureString (string text, Font font, SizeF layoutArea, StringFormat stringFormat, out int charactersFitted, out int linesFilled) {       \r
-                       //TBD: charcount\r
-                       throw new NotImplementedException();\r
+                       linesFilled = 0;\r
+                       charactersFitted = 0;\r
+\r
+                       int[] statistics = new int[2];\r
+                       SizeF sz = MeasureString(text, font, stringFormat, layoutArea.Width, layoutArea.Height, statistics);\r
+                       linesFilled = statistics[0];\r
+                       charactersFitted = statistics[1];\r
+                       return sz;\r
                }\r
                #endregion\r
 \r
@@ -1509,25 +1942,16 @@ namespace System.Drawing {
 \r
                #region Reset (Clip and Transform)\r
                public void ResetClip () {\r
-                       java.awt.Graphics2D g = NativeObject;\r
-                       g.setClip(null);\r
-\r
+                       _clip.MakeInfinite();\r
+                       RestoreBaseClip();\r
+                       NativeObject.clip(_clip);\r
                }\r
 \r
                public void ResetTransform () {\r
-                       _transform = new Matrix(1,0,0,1,0,0);\r
-                       UpdateInternalTransform();\r
+                       _transform.Reset();\r
                }\r
                #endregion\r
 \r
-               public GraphicsState Save () {\r
-                       throw new NotImplementedException();\r
-               }\r
-\r
-               public void Restore (GraphicsState gstate) {\r
-                       throw new NotImplementedException();\r
-               }\r
-\r
                #region RotateTransform\r
                public void RotateTransform (float angle) {\r
                        RotateTransform (angle, MatrixOrder.Prepend);\r
@@ -1573,9 +1997,7 @@ namespace System.Drawing {
                        if(g == null)\r
                                throw new NullReferenceException();\r
                        \r
-                       SetNativeClip(\r
-                               CombineClipArea(g.GetNativeClip(),\r
-                               combineMode));\r
+                       CombineClipArea(g._clip.NativeObject, combineMode);\r
                }\r
 \r
                public void SetClip (Rectangle rect, CombineMode combineMode) {\r
@@ -1589,67 +2011,84 @@ namespace System.Drawing {
                        if(region == null)\r
                                throw new ArgumentNullException("region");\r
 \r
-                       if(region == Region.InfiniteRegion) {\r
-                               SetNativeClip(null);\r
-                               return;\r
-                       }\r
-\r
-                       SetNativeClip(CombineClipArea(region.NativeObject,combineMode));\r
+                       CombineClipArea((geom.Area)region.NativeObject.clone(),combineMode);\r
                }\r
                \r
                public void SetClip (GraphicsPath path, CombineMode combineMode) {\r
                        if(path == null)\r
                                throw new ArgumentNullException("path");\r
 \r
-                       SetNativeClip(CombineClipArea(new java.awt.geom.Area(path.NativeObject),combineMode));\r
+                       CombineClipArea(new geom.Area(path.NativeObject), combineMode);\r
                }\r
                #endregion\r
 \r
                #region Clipping Staff [INTERNAL]\r
+               internal Region ScaledClip {\r
+                       get {\r
+                               return _clip.Clone();\r
+                       }\r
+                       set {\r
+                               _clip.NativeObject.reset();\r
+                               _clip.NativeObject.add(value.NativeObject);\r
+                       }\r
+               }\r
                internal void SetClip(float x,float y,float width,float height,CombineMode combineMode) {                                       \r
-                       SetNativeClip(CombineClipArea(new geom.Area(\r
-                               new geom.Rectangle2D.Float(x,y,width,height)),combineMode));\r
-               }\r
-\r
-               geom.Area CombineClipArea(java.awt.geom.Area area, CombineMode combineMode) {\r
-                       if (combineMode == CombineMode.Replace)\r
-                               return area;\r
-\r
-                       geom.Area curClip = GetNativeClip();\r
-                       switch(combineMode) {\r
-                               case CombineMode.Complement:\r
-                                       curClip.add(area);\r
-                                       break;\r
-                               case CombineMode.Exclude:\r
-                                       curClip.subtract(area);\r
-                                       break;\r
-                               case CombineMode.Intersect:\r
-                                       curClip.intersect(area);\r
-                                       break;\r
-                               case CombineMode.Union:\r
-                                       curClip.add(area);\r
-                                       break;\r
-                               case CombineMode.Xor:\r
-                                       curClip.exclusiveOr(area);\r
-                                       break;\r
-                               default:\r
-                                       throw new ArgumentOutOfRangeException();                                        \r
+                       CombineClipArea(new geom.Area(\r
+                               new geom.Rectangle2D.Float(x,y,width,height)),combineMode);\r
+               }\r
+\r
+               void CombineClipArea(geom.Area area, CombineMode combineMode) {\r
+                       geom.AffineTransform t = GetFinalTransform();\r
+                       if (!t.isIdentity())\r
+                               area.transform(t);\r
+                       if (combineMode == CombineMode.Replace) {\r
+                               _clip.NativeObject.reset();\r
+                               _clip.NativeObject.add(area);\r
                        }\r
-                       \r
-                       return curClip;\r
+                       else {\r
+                               geom.Area curClip = _clip.NativeObject;\r
+                               switch(combineMode) {\r
+                                       case CombineMode.Complement:\r
+                                               curClip.add(area);\r
+                                               break;\r
+                                       case CombineMode.Exclude:\r
+                                               curClip.subtract(area);\r
+                                               break;\r
+                                       case CombineMode.Intersect:\r
+                                               curClip.intersect(area);\r
+                                               break;\r
+                                       case CombineMode.Union:\r
+                                               curClip.add(area);\r
+                                               break;\r
+                                       case CombineMode.Xor:\r
+                                               curClip.exclusiveOr(area);\r
+                                               break;\r
+                                       default:\r
+                                               throw new ArgumentOutOfRangeException();                                        \r
+                               }\r
+                       }\r
+\r
+                       RestoreBaseClip();\r
+                       NativeObject.clip(_clip);\r
                }\r
-               \r
-               void SetNativeClip(awt.Shape s) {\r
-                       NativeObject.setClip(s);\r
+\r
+               internal void IntersectScaledClipWithBase(awt.Shape clip) {\r
+                       NativeObject.clip(clip);\r
                }\r
 \r
-               geom.Area GetNativeClip() {\r
-                       awt.Shape clip = NativeObject.getClip();\r
-                       return clip != null ? new geom.Area(clip) : (geom.Area)Region.InfiniteRegion.NativeObject.clone();\r
+               void RestoreBaseClip() {\r
+                       if (_nextGraphicsState == null) {\r
+                               NativeObject.setClip(_windowRect);\r
+                               return;\r
+                       }\r
+\r
+                       _nextGraphicsState.RestoreBaseClip(this);\r
                }\r
+               \r
                #endregion\r
                \r
                #region TransformPoints\r
+               [MonoTODO]\r
                public void TransformPoints (CoordinateSpace destSpace, CoordinateSpace srcSpace, PointF [] pts) {\r
                        //TBD:CoordinateSpace\r
                        java.awt.geom.AffineTransform tr = this.Transform.NativeObject;\r
@@ -1663,6 +2102,7 @@ namespace System.Drawing {
                        }\r
                }\r
 \r
+               [MonoTODO]\r
                public void TransformPoints (CoordinateSpace destSpace, CoordinateSpace srcSpace, Point [] pts) {                                               \r
                        //TBD:CoordinateSpace\r
                        java.awt.geom.AffineTransform tr = this.Transform.NativeObject;\r
@@ -1684,9 +2124,27 @@ namespace System.Drawing {
 \r
                \r
                public void TranslateClip (float dx, float dy) {\r
-                       geom.Area clip = GetNativeClip();\r
-                       clip.transform(geom.AffineTransform.getTranslateInstance(dx, dy));\r
-                       SetNativeClip(clip);\r
+                       double x = dx;\r
+                       double y = dy;\r
+                       geom.AffineTransform f = GetFinalTransform();\r
+\r
+                       if (!f.isIdentity()) {\r
+                               double[] p = new double[] {x, y};\r
+                               f.deltaTransform(p, 0, p, 0, 1);\r
+\r
+                               x = p[0];\r
+                               y = p[1];\r
+                       }\r
+\r
+                       // It seems .Net does exactly this...\r
+                       x = Math.Floor(x+0.96875);\r
+                       y = Math.Floor(y+0.96875);\r
+\r
+                       geom.AffineTransform t = geom.AffineTransform.getTranslateInstance(x, y);\r
+\r
+                       _clip.NativeObject.transform(t);\r
+                       RestoreBaseClip();\r
+                       NativeObject.clip(_clip);\r
                }\r
                #endregion\r
 \r
@@ -1706,14 +2164,12 @@ namespace System.Drawing {
                #region Properties [Partial TODO]\r
                public Region Clip {\r
                        get {\r
-                               java.awt.Graphics2D g = NativeObject;\r
-                               java.awt.Shape s = g.getClip();                         \r
-                               if(s != null) {\r
-                                       return new Region(new java.awt.geom.Area(s));\r
-                               }\r
-                               else {\r
-                                       return Region.InfiniteRegion.Clone();\r
-                               }\r
+                               Region r = _clip.Clone();\r
+                               geom.AffineTransform t = GetFinalTransform();\r
+                               if (!t.isIdentity())\r
+                                       r.NativeObject.transform(t.createInverse());\r
+\r
+                               return r;\r
                        }\r
                        set {\r
                                SetClip (value, CombineMode.Replace);\r
@@ -1722,10 +2178,18 @@ namespace System.Drawing {
 \r
                public RectangleF ClipBounds {\r
                        get {\r
-                               java.awt.Graphics2D g = NativeObject;\r
-                               java.awt.Rectangle r = g.getClipBounds();\r
-                               RectangleF rect = new RectangleF ((float)r.getX(),(float)r.getY(),(float)r.getWidth(),(float)r.getHeight());\r
-                               return rect;\r
+                               awt.Shape shape = _clip.NativeObject;\r
+                               if (shape == null)\r
+                                       shape = Region.InfiniteRegion.NativeObject;\r
+\r
+                               geom.RectangularShape r = shape.getBounds2D();\r
+                               geom.AffineTransform t = GetFinalTransform();\r
+                               if (!t.isIdentity()) {\r
+                                       geom.AffineTransform it = t.createInverse();\r
+                                       r = it.createTransformedShape(r).getBounds2D();\r
+                               }\r
+\r
+                               return new RectangleF (r);\r
                        }\r
                }\r
 \r
@@ -1848,20 +2312,16 @@ namespace System.Drawing {
 \r
                public bool IsClipEmpty {\r
                        get {\r
-                               java.awt.Graphics2D g = NativeObject;\r
-                               awt.Shape clip = g.getClip();\r
-                               if (clip == null)\r
-                                       return false;\r
-                               return new geom.Area(clip).isEmpty();\r
+                               return _clip.IsEmpty(this);\r
                        }\r
                }\r
 \r
                public bool IsVisibleClipEmpty {\r
                        get {\r
-                               awt.Shape clip = NativeObject.getClip();\r
-                               if (clip == null)\r
-                                       return false;\r
-                               return !clip.intersects(0, 0, _image.Width, _image.Height);\r
+                               if (_clip.IsEmpty(this))\r
+                                       return true;\r
+\r
+                               return VisibleClipBounds.IsEmpty;\r
                        }\r
                }\r
 \r
@@ -1871,7 +2331,6 @@ namespace System.Drawing {
                        }\r
                        set {\r
                                _pageScale = value;\r
-                               UpdateInternalTransform();\r
                        }\r
                }\r
 \r
@@ -1881,22 +2340,28 @@ namespace System.Drawing {
                        }\r
                        set {\r
                                _pageUnit = value;\r
-                               UpdateInternalTransform();\r
                        }\r
                }\r
 \r
-               internal void UpdateInternalTransform()\r
-               {\r
-                       float new_scale = _pageScale * _unitConversion[ (int)PageUnit ];\r
-                       Matrix mx = _transform.Clone();\r
+               static internal geom.AffineTransform GetFinalTransform(\r
+                       geom.AffineTransform transform, GraphicsUnit pageUnit, float pageScale) {\r
+                       geom.AffineTransform t = null;\r
+                       if (pageUnit != GraphicsUnit.Display) {\r
+                               float scale = pageScale * _unitConversion[ (int)pageUnit ];\r
+                               if (Math.Abs(scale-1f) > float.Epsilon)\r
+                                       t = geom.AffineTransform.getScaleInstance(scale, scale);\r
+                       }\r
 \r
-                       mx.Scale( new_scale, new_scale, MatrixOrder.Prepend );\r
-                       mx.Translate(\r
-                               mx.OffsetX * new_scale - mx.OffsetX,\r
-                               mx.OffsetY * new_scale - mx.OffsetY, MatrixOrder.Append);\r
+                       if (t != null)\r
+                               t.concatenate(transform);\r
+                       else\r
+                               t = transform;\r
+                       \r
+                       return t;\r
+               }\r
 \r
-                       java.awt.Graphics2D g = NativeObject;\r
-                       g.setTransform( mx.NativeObject );\r
+               geom.AffineTransform GetFinalTransform() {\r
+                       return GetFinalTransform(_transform.NativeObject, PageUnit, PageScale);\r
                }\r
 \r
                public PixelOffsetMode PixelOffsetMode {\r
@@ -1908,6 +2373,7 @@ namespace System.Drawing {
                        }\r
                }\r
 \r
+               [MonoTODO]\r
                public Point RenderingOrigin {\r
                        get {\r
                                throw new NotImplementedException();\r
@@ -1986,56 +2452,111 @@ namespace System.Drawing {
 \r
                public TextRenderingHint TextRenderingHint {\r
                        get {\r
-                               awt.RenderingHints hints = NativeObject.getRenderingHints();\r
-                               if(hints.containsKey(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING)) {\r
-                                       if(hints.get(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING) == \r
-                                               java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON)\r
-                                               return TextRenderingHint.AntiAlias;\r
-                                       if(hints.get(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING) == \r
-                                               java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)\r
-                                               return TextRenderingHint.SingleBitPerPixel;\r
-                               }\r
-                               return TextRenderingHint.SystemDefault;\r
+                               return _textRenderingHint;\r
+//                             awt.RenderingHints hints = NativeObject.getRenderingHints();\r
+//                             if(hints.containsKey(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING)) {\r
+//                                     if(hints.get(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING) == \r
+//                                             java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON)\r
+//                                             return TextRenderingHint.AntiAlias;\r
+//                                     if(hints.get(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING) == \r
+//                                             java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)\r
+//                                             return TextRenderingHint.SingleBitPerPixel;\r
+//                             }\r
+//                             //return TextRenderingHint.SystemDefault;\r
+//                             return TextRenderingHint.SingleBitPerPixelGridFit;\r
                        }\r
 \r
                        set {\r
-                               // TODO implement\r
+                               _textRenderingHint = value;\r
                                awt.RenderingHints hints = NativeObject.getRenderingHints();\r
                                switch (value) {\r
                                        case TextRenderingHint.AntiAlias:\r
                                        case TextRenderingHint.AntiAliasGridFit:\r
                                        case TextRenderingHint.ClearTypeGridFit:\r
-                                       case TextRenderingHint.SingleBitPerPixel:\r
+//                                     case TextRenderingHint.SystemDefault:\r
+                                               hints.put(awt.RenderingHints.KEY_TEXT_ANTIALIASING,\r
+                                                       awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON);\r
+                                               break;\r
+                                       \r
                                        case TextRenderingHint.SingleBitPerPixelGridFit:\r
+                                               hints.put(awt.RenderingHints.KEY_TEXT_ANTIALIASING,\r
+                                                       awt.RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);\r
+                                               break;\r
+\r
+                                       case TextRenderingHint.SingleBitPerPixel:\r
+                                               hints.put(awt.RenderingHints.KEY_TEXT_ANTIALIASING,\r
+                                                       awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);\r
+                                               break;\r
+\r
                                        case TextRenderingHint.SystemDefault:\r
+                                               hints.put(awt.RenderingHints.KEY_TEXT_ANTIALIASING,\r
+                                                       awt.RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);\r
                                                break;\r
                                }\r
+                               \r
+                               NativeObject.setRenderingHints(hints);\r
                        }\r
                }\r
 \r
                public Matrix Transform {\r
                        get {\r
-                               return _transform;\r
+                               return _transform.Clone();\r
                        }\r
                        set {\r
-                               _transform = value.Clone();\r
-                               UpdateInternalTransform();\r
+                               if (value == null)\r
+                                       throw new ArgumentNullException("matrix");\r
+\r
+                               if (!value.IsInvertible)\r
+                                       throw new ArgumentException("Invalid parameter used.");\r
+\r
+                               value.CopyTo(_transform);\r
+                       }\r
+               }\r
+\r
+               internal Matrix BaseTransform {\r
+                       get {\r
+                               return new Matrix(NativeObject.getTransform());\r
+                       }\r
+                       set {\r
+                               NativeObject.setTransform(value.NativeObject);\r
+                       }\r
+               }\r
+\r
+               internal void PrependBaseTransform(geom.AffineTransform t) {\r
+                       NativeObject.transform(t);\r
+               }\r
+\r
+               internal awt.Shape VisibleShape {\r
+                       get {\r
+                               return _windowRect;\r
                        }\r
                }\r
 \r
                public RectangleF VisibleClipBounds {\r
                        get {\r
-                               RectangleF bounds = ClipBounds;\r
-                               bounds.Intersect(new RectangleF(0, 0, _image.Width, _image.Height));\r
-                               return bounds;\r
+                               if (_clip.IsEmpty(this))\r
+                                       return RectangleF.Empty;\r
+\r
+                               geom.Rectangle2D r = _clip.NativeObject.getBounds2D();\r
+                               awt.Shape clip = NativeObject.getClip();\r
+                               geom.Rectangle2D clipBounds = (clip != null) ? clip.getBounds2D() : _windowRect;\r
+                               geom.Rectangle2D.intersect(r, clipBounds, r);\r
+                               if ((r.getWidth() <= 0) || (r.getHeight() <= 0))\r
+                                       return RectangleF.Empty;\r
+\r
+                               geom.AffineTransform t = GetFinalTransform();\r
+                               if (!t.isIdentity()) {\r
+                                       geom.AffineTransform it = t.createInverse();\r
+                                       r = it.createTransformedShape(r).getBounds2D();\r
+                               }\r
+\r
+                               return new RectangleF (r);\r
                        }\r
                }\r
 \r
                void ConcatenateTransform(geom.AffineTransform transform, MatrixOrder order) {\r
                        geom.AffineTransform at = _transform.NativeObject;\r
                        Matrix.Multiply(at, transform, order);\r
-\r
-                       UpdateInternalTransform();\r
                }\r
                #endregion\r
        }\r