context: using System;
  using System.Drawing.Drawing2D;
  using java.lang;
  
  using java.awt;
  using java.awt.geom;
  using sun.dc.path;
  using sun.dc.pr;
  
  namespace System.Drawing {
  
  	internal enum PenFit {
  		NotThin,
  		Thin,
  		ThinAntiAlias
  	}
  
  	internal class AdvancedStroke : Stroke {
  
  		public const float PenUnits = 0.01f;
  		public const int MinPenUnits = 100;
  		public const int MinPenUnitsAA = 20;
  		public const float MinPenSizeAA = PenUnits * MinPenUnitsAA;
  		public const double MinPenSizeAASquared = (MinPenSizeAA * MinPenSizeAA);
  		public const double MinPenSizeSquared = 1.000000001;
  		public const double MinPenSizeNorm = 1.5;
  		public const double MinPenSizeSquaredNorm = (MinPenSizeNorm * MinPenSizeNorm);
  
  		/**
  		 * Joins path segments by extending their outside edges until
  		 * they meet.
  		 */
  		public const int JOIN_MITER = 0;
  
  		/**
  		 * Joins path segments by rounding off the corner at a radius
  		 * of half the line width.
  		 */
  		public const int JOIN_ROUND = 1;
  
  		/**
  		 * Joins path segments by connecting the outer corners of their
  		 * wide outlines with a straight segment.
  		 */
  		public const int JOIN_BEVEL = 2;
  
  		/**
  		 * Ends unclosed subpaths and dash segments with no added
  		 * decoration.
  		 */
  		public const int CAP_BUTT = 0;
  
  		/**
  		 * Ends unclosed subpaths and dash segments with a round
  		 * decoration that has a radius equal to half of the width
  		 * of the pen.
  		 */
  		public const int CAP_ROUND = 1;
  
  		/**
  		 * Ends unclosed subpaths and dash segments with a square
  		 * projection that extends beyond the end of the segment
  		 * to a distance equal to half of the line width.
  		 */
  		public const int CAP_SQUARE = 2;
  
  		float width;
  
  		int join;
  		int cap;
  		float miterlimit;
  
  		float[] dash;
  		float dash_phase;
  
  		AffineTransform _penTransform;
  		AffineTransform _outputTransform;
  		PenFit _penFit;
  
  		/**
  		 * Constructs a new <code>AdvancedStroke</code> with the specified
  		 * attributes.
  		 * @param width the width of this <code>AdvancedStroke</code>.  The
  		 *         width must be greater than or equal to 0.0f.  If width is
  		 *         set to 0.0f, the stroke is rendered as the thinnest
  		 *         possible line for the target device and the antialias
  		 *         hint setting.
  		 * @param cap the decoration of the ends of a <code>AdvancedStroke</code>
  		 * @param join the decoration applied where path segments meet
  		 * @param miterlimit the limit to trim the miter join.  The miterlimit
  		 *        must be greater than or equal to 1.0f.
  		 * @param dash the array representing the dashing pattern
  		 * @param dash_phase the offset to start the dashing pattern
  		 * @throws IllegalArgumentException if <code>width</code> is negative
  		 * @throws IllegalArgumentException if <code>cap</code> is not either
  		 *         CAP_BUTT, CAP_ROUND or CAP_SQUARE
  		 * @throws IllegalArgumentException if <code>miterlimit</code> is less
  		 *         than 1 and <code>join</code> is JOIN_MITER
  		 * @throws IllegalArgumentException if <code>join</code> is not
  		 *         either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER
  		 * @throws IllegalArgumentException if <code>dash_phase</code>
  		 *         is negative and <code>dash</code> is not <code>null</code>
  		 * @throws IllegalArgumentException if the length of
  		 *         <code>dash</code> is zero
  		 * @throws IllegalArgumentException if dash lengths are all zero.
  		 */
  		public AdvancedStroke(float width, int cap, int join, float miterlimit,
  			float[] dash, float dash_phase, AffineTransform penTransform,
  			AffineTransform outputTransform, PenFit penFit) {
  			if (width < 0.0f) {
  				throw new IllegalArgumentException("negative width");
  			}
  			if (cap != CAP_BUTT && cap != CAP_ROUND && cap != CAP_SQUARE) {
  				throw new IllegalArgumentException("illegal end cap value");
  			}
  			if (join == JOIN_MITER) {
  				if (miterlimit < 1.0f) {
  					throw new IllegalArgumentException("miter limit < 1");
  				}
  			} else if (join != JOIN_ROUND && join != JOIN_BEVEL) {
  				throw new IllegalArgumentException("illegal line join value");
  			}
  			if (dash != null) {
  				if (dash_phase < 0.0f) {
  					throw new IllegalArgumentException("negative dash phase");
  				}
  				bool allzero = true;
  				for (int i = 0; i < dash.Length; i++) {
  					float d = dash[i];
  					if (d > 0.0) {
  						allzero = false;
  					} else if (d < 0.0) {
  						throw new IllegalArgumentException("negative dash length");
  					}
  				}
  				if (allzero) {
  					throw new IllegalArgumentException("dash lengths all zero");
  				}
  			}
  			this.width	= width;
  			this.cap	= cap;
  			this.join	= join;
  			this.miterlimit	= miterlimit;
  			if (dash != null) {
  				this.dash = (float []) dash.Clone();
  			}
  			this.dash_phase	= dash_phase;
  			this._penTransform = penTransform;
  			this._outputTransform = outputTransform;
  			this._penFit = penFit;
  		}
  
  		/**
  		 * Constructs a solid <code>AdvancedStroke</code> with the specified 
  		 * attributes.
  		 * @param width the width of the <code>AdvancedStroke</code>
  		 * @param cap the decoration of the ends of a <code>AdvancedStroke</code>
  		 * @param join the decoration applied where path segments meet
  		 * @param miterlimit the limit to trim the miter join
  		 * @throws IllegalArgumentException if <code>width</code> is negative
  		 * @throws IllegalArgumentException if <code>cap</code> is not either
  		 *         CAP_BUTT, CAP_ROUND or CAP_SQUARE
  		 * @throws IllegalArgumentException if <code>miterlimit</code> is less
  		 *         than 1 and <code>join</code> is JOIN_MITER
  		 * @throws IllegalArgumentException if <code>join</code> is not
  		 *         either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER
  		 */
  		public AdvancedStroke(float width, int cap, int join, float miterlimit) :
  			this(width, cap, join, miterlimit, null, 0.0f, null, null, PenFit.NotThin) {
  		}
  
  		/**
  		 * Constructs a solid <code>AdvancedStroke</code> with the specified 
  		 * attributes.  The <code>miterlimit</code> parameter is 
  		 * unnecessary in cases where the default is allowable or the 
  		 * line joins are not specified as JOIN_MITER.
  		 * @param width the width of the <code>AdvancedStroke</code>
  		 * @param cap the decoration of the ends of a <code>AdvancedStroke</code>
  		 * @param join the decoration applied where path segments meet
  		 * @throws IllegalArgumentException if <code>width</code> is negative
  		 * @throws IllegalArgumentException if <code>cap</code> is not either
  		 *         CAP_BUTT, CAP_ROUND or CAP_SQUARE
  		 * @throws IllegalArgumentException if <code>join</code> is not
  		 *         either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER
  		 */
  		public AdvancedStroke(float width, int cap, int join) :
  			this(width, cap, join, 10.0f, null, 0.0f, null, null, PenFit.NotThin) {
  		}
  
  		/**
  		 * Constructs a solid <code>AdvancedStroke</code> with the specified 
  		 * line width and with default values for the cap and join 
  		 * styles.
  		 * @param width the width of the <code>AdvancedStroke</code>
  		 * @throws IllegalArgumentException if <code>width</code> is negative
  		 */
  		public AdvancedStroke(float width) :
  			this(width, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f, null, null, PenFit.NotThin) {
  		}
  
  		/**
  		 * Constructs a new <code>AdvancedStroke</code> with defaults for all 
  		 * attributes.
  		 * The default attributes are a solid line of width 1.0, CAP_SQUARE,
  		 * JOIN_MITER, a miter limit of 10.0.
  		 */
  		public AdvancedStroke() :
  			this(1.0f, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f, null, null, PenFit.NotThin) {
  		}
  
  
  		/**
  		 * Returns a <code>Shape</code> whose interior defines the 
  		 * stroked outline of a specified <code>Shape</code>.
  		 * @param s the <code>Shape</code> boundary be stroked
  		 * @return the <code>Shape</code> of the stroked outline.
  		 */
  		public Shape createStrokedShape(Shape s) {
  			FillAdapter filler = new FillAdapter();
  			PathStroker stroker = new PathStroker(filler);
  			PathConsumer consumer;
  
  			stroker.setPenDiameter(width);
  			switch (_penFit) {
  				case PenFit.Thin:
  					stroker.setPenFitting(PenUnits, MinPenUnits);
  					break;
  				case PenFit.ThinAntiAlias:
  					stroker.setPenFitting(PenUnits, MinPenUnitsAA);
  					break;
  			}
  
  			float[] t4 = null;
  			if (PenTransform != null && !PenTransform.isIdentity() && (PenTransform.getDeterminant() > 1e-25)) {
  				t4 = new float[]{
  					(float)PenTransform.getScaleX(), (float)PenTransform.getShearY(), 
  					(float)PenTransform.getShearX(), (float)PenTransform.getScaleY()
  				};
  			}
  
  			float[] t6 = null;
  			if (OutputTransform != null && !OutputTransform.isIdentity()) {
  				t6 = new float[] {
  					(float)OutputTransform.getScaleX(), (float)OutputTransform.getShearY(), 
  					(float)OutputTransform.getShearX(), (float)OutputTransform.getScaleY(),
  					(float)OutputTransform.getTranslateX(), (float)OutputTransform.getTranslateY()
  				};
  			}
  
  			stroker.setPenT4(t4);
  			stroker.setOutputT6(t6);
  			stroker.setCaps(RasterizerCaps[cap]);
  			stroker.setCorners(RasterizerCorners[join], miterlimit);
  			if (dash != null) {
  				PathDasher dasher = new PathDasher(stroker);
  				dasher.setDash(dash, dash_phase);
  				dasher.setDashT4(t4);
  				consumer = dasher;
  			} else {
  				consumer = stroker;
  			}
  
  			PathIterator pi = s.getPathIterator(null);
  
  			try {
  				consumer.beginPath();
  				bool pathClosed = false;
  				float mx = 0.0f;
  				float my = 0.0f;
  				float[] point  = new float[6];
  
  				while (!pi.isDone()) {
  					int type = pi.currentSegment(point);
  					if (pathClosed == true) {
  						pathClosed = false;
  						if (type !=  PathIterator__Finals.SEG_MOVETO) {
  							// Force current point back to last moveto point
  							consumer.beginSubpath(mx, my);
  						}
  					}
  					switch ((GraphicsPath.JPI)type) {
  						case GraphicsPath.JPI.SEG_MOVETO:
  							mx = point[0];
  
gt: 							my = point[1];