internal EllipseIterator(Ellipse e, AffineTransform at) { _x = e.GetX(); _y = e.GetY(); _w = e.GetWidth(); _h = e.GetHeight(); _affine = at; if (_w < 0 || _h < 0) { _index = 6; } }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Constructor * @param r * @param at */ internal RectIterator(Rectangle r, AffineTransform at) { _x = r.GetX(); _y = r.GetY(); _w = r.GetWidth(); _h = r.GetHeight(); _affine = at; if (_w < 0 || _h < 0) { _index = 6; } }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// internal ArcIterator(Arc a, AffineTransform at) { _w = a.GetWidth() / 2.0; _h = a.GetHeight() / 2.0; _x = a.GetX() + _w; _y = a.GetY() + _h; _angStRad = -MathEx.ToRadians(a.GetAngleStart()); _affine = at; double ext = -a.GetAngleExtent(); if (ext >= 360.0 || ext <= -360) { _arcSegs = 4; _increment = Math.PI / 2; // btan(Math.PI / 2); _cv = 0.5522847498307933; if (ext < 0) { _increment = -_increment; _cv = -_cv; } } else { _arcSegs = (int)MathEx.Ceil(MathEx.Abs(ext) / 90.0); _increment = MathEx.ToRadians(ext / _arcSegs); _cv = Btan(_increment); if (_cv == 0) { _arcSegs = 0; } } switch (a.GetArcType()) { case Arc.OPEN: _lineSegs = 0; break; case Arc.CHORD: _lineSegs = 1; break; case Arc.PIE: _lineSegs = 2; break; } if (_w < 0 || _h < 0) { _arcSegs = _lineSegs = -1; } }
internal static AffineTransform ToMatrix(MatrixFP matrixFP) { if (matrixFP == null) { return null; } if (matrixFP.IsIdentity()) { return new AffineTransform(); } AffineTransform matrix = new AffineTransform(SingleFP.ToDouble(matrixFP.ScaleX), SingleFP.ToDouble(matrixFP.RotateX), SingleFP.ToDouble(matrixFP.RotateY), SingleFP.ToDouble(matrixFP.ScaleY), SingleFP.ToDouble(matrixFP.TranslateX), SingleFP.ToDouble(matrixFP.TranslateY)); return matrix; }
internal static MatrixFP ToMatrixFP(AffineTransform matrix) { if (matrix == null) { return null; } if (matrix.IsIdentity()) { return MatrixFP.Identity; } MatrixFP matrixFP = new MatrixFP(SingleFP.FromDouble(matrix.GetScaleX()), SingleFP.FromDouble(matrix.GetScaleY()), SingleFP.FromDouble(matrix.GetShearX()), SingleFP.FromDouble(matrix.GetShearY()), SingleFP.FromDouble(matrix.GetTranslateX()), SingleFP.FromDouble(matrix.GetTranslateY())); return matrixFP; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns an iteration object that defines the boundary of the * shape of this <code>QuadCurve</code>. * The iterator for this class is not multi-threaded safe, * which means that this <code>QuadCurve</code> class does not * guarantee that modifications to the geometry of this * <code>QuadCurve</code> object do not affect any iterations of * that geometry that are already in process. * @param at an optional {@link AffineTransform} to apply to the * shape boundary * @return a {@link PathIterator} object that defines the boundary * of the shape. */ public PathIterator GetPathIterator(AffineTransform at) { return new QuadIterator(this, at); }
public AreaIterator(ArrayList curves, AffineTransform at) { _curves = curves; _transform = at; if (curves.Count >= 1) { _thiscurve = (Curve)curves[0]; } }
internal RoundRectIterator(RoundRectangle rr, AffineTransform at) { _x = rr.GetX(); _y = rr.GetY(); _w = rr.GetWidth(); _h = rr.GetHeight(); _aw = Math.Min(_w, Math.Abs(rr.GetArcWidth())); _ah = Math.Min(_h, Math.Abs(rr.GetArcHeight())); _affine = at; if (_aw < 0 || _ah < 0) { // Don't draw anything... _index = CTRLPTS.Length; } }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns an iteration object that defines the boundary of the * arc. * This iterator is multithread safe. * <code>Arc</code> guarantees that * modifications to the geometry of the arc * do not affect any iterations of that geometry that * are already in process. * * @param at an optional <CODE>AffineTransform</CODE> to be applied * to the coordinates as they are returned in the iteration, or null * if the untransformed coordinates are desired. * * @return A <CODE>IPathIterator</CODE> that defines the arc's boundary. */ public override PathIterator GetPathIterator(AffineTransform at) { return new ArcIterator(this, at); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Transforms the geometry of this <code>Area</code> using the specified * {@link AffineTransform}. The geometry is transformed in place, which * permanently changes the enclosed area defined by this object. * @param t the transformation used to transform the area * @throws NullPointerException if <code>t</code> is null */ public void Transform(AffineTransform t) { if (t == null) { throw new NullReferenceException("transform must not be null"); } // REMIND: A simpler operation can be performed for some types // of transform. _curves = PathToCurves(GetPathIterator(t)); InvalidateBounds(); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns a transform representing a translation transformation. * The matrix representing the returned transform is: * <pre> * [ 1 0 tx ] * [ 0 1 ty ] * [ 0 0 1 ] * </pre> * @param tx the distance by which coordinates are translated in the * X axis direction * @param ty the distance by which coordinates are translated in the * Y axis direction * @return an <code>AffineTransform</code> object that represents a * translation transformation, created with the specified vector. */ public static AffineTransform GetTranslateInstance(double tx, double ty) { var trans = new AffineTransform(); trans.SetToTranslation(tx, ty); return trans; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns a transform representing a scaling transformation. * The matrix representing the returned transform is: * <pre> * [ sx 0 0 ] * [ 0 sy 0 ] * [ 0 0 1 ] * </pre> * @param sx the factor by which coordinates are scaled along the * X axis direction * @param sy the factor by which coordinates are scaled along the * Y axis direction * @return an <code>AffineTransform</code> object that scales * coordinates by the specified factors. */ public static AffineTransform GetScaleInstance(double sx, double sy) { var tx = new AffineTransform(); tx.SetToScale(sx, sy); return tx; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns a transform representing a rotation transformation. * The matrix representing the returned transform is: * <pre> * [ Cos(theta) -Sin(theta) 0 ] * [ Sin(theta) Cos(theta) 0 ] * [ 0 0 1 ] * </pre> * Rotating by a positive angle theta rotates points on the positive * X axis toward the positive Y axis. * also the discussion of * <a href="#quadrantapproximation">Handling 90-Degree Rotations</a> * above. * @param theta the angle of rotation measured in radians * @return an <code>AffineTransform</code> object that is a rotation * transformation, created with the specified angle of rotation. */ public static AffineTransform GetRotateInstance(double theta) { var tx = new AffineTransform(); tx.SetToRotation(theta); return tx; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Constructs a new <code>AffineTransform</code> that is a copy of * the specified <code>AffineTransform</code> object. * @param Tx the <code>AffineTransform</code> object to copy */ public AffineTransform(AffineTransform tx) { _m00 = tx._m00; _m10 = tx._m10; _m01 = tx._m01; _m11 = tx._m11; _m02 = tx._m02; _m12 = tx._m12; _state = tx._state; _type = tx._type; }
public abstract PathIterator GetPathIterator(AffineTransform at);
internal QuadIterator(QuadCurve q, AffineTransform at) { _quad = q; _affine = at; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 15JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Constructs a {@code LinearGradientBrush}. * * @param start the gradient axis start {@code Point} in user space * @param end the gradient axis end {@code Point} in user space * @param fractions numbers ranging from 0 to 255 specifying the * distribution of colors along the gradient * @param colors array of colors corresponding to each fractional Value * @param fillType either {@code NO_CYCLE}, {@code REFLECT}, * or {@code REPEAT} * @param gradientTransform transform to apply to the gradient * * @throws NullPointerException * if one of the points is null, * or {@code fractions} array is null, * or {@code colors} array is null, * or {@code cycleMethod} is null, * or {@code colorSpace} is null, * or {@code gradientTransform} is null * @throws IllegalArgumentException * if start and end points are the same points, * or {@code fractions.length != colors.length}, * or {@code colors} is less than 2 in size, * or a {@code fractions} Value is less than 0.0 or greater than 1.0, * or the {@code fractions} are not provided in strictly increasing order */ public LinearGradientBrush(Point start, Point end, int[] fractions, Color[] colors, AffineTransform gradientTransform, int fillType) { if (fractions == null) { throw new NullReferenceException("Fractions array cannot be null"); } if (colors == null) { throw new NullReferenceException("Colors array cannot be null"); } if (gradientTransform == null) { throw new NullReferenceException("Gradient transform cannot be " + "null"); } if (fractions.Length != colors.Length) { throw new ArgumentException("Colors and fractions must " + "have equal size"); } if (colors.Length < 2) { throw new ArgumentException("User must specify at least " + "2 colors"); } // check that values are in the proper range and progress // in increasing order from 0 to 1 int previousFraction = -255; for (int i = 0; i < fractions.Length; i++) { int currentFraction = fractions[i]; if (currentFraction < 0 || currentFraction > 255) { throw new ArgumentException("Fraction values must " + "be in the range 0 to 255: " + currentFraction); } if (currentFraction <= previousFraction) { throw new ArgumentException("Keyframe fractions " + "must be increasing: " + currentFraction); } previousFraction = currentFraction; } // We have to deal with the cases where the first gradient stop is not // equal to 0 and/or the last gradient stop is not equal to 1. // In both cases, create a new point and replicate the previous // extreme point's color. bool fixFirst = false; bool fixLast = false; int len = fractions.Length; int off = 0; if (fractions[0] != 0) { // first stop is not equal to zero, fix this condition fixFirst = true; len++; off++; } if (fractions[fractions.Length - 1] != 255) { // last stop is not equal to one, fix this condition fixLast = true; len++; } this._fractions = new int[len]; Array.Copy(fractions, 0, this._fractions, off, fractions.Length); this._colors = new Color[len]; Array.Copy(colors, 0, this._colors, off, colors.Length); if (fixFirst) { this._fractions[0] = 0; this._colors[0] = colors[0]; } if (fixLast) { this._fractions[len - 1] = 255; this._colors[len - 1] = colors[colors.Length - 1]; } // copy the gradient transform this._gradientTransform = new AffineTransform(gradientTransform); // determine transparency bool opaque = true; for (int i = 0; i < colors.Length; i++) { opaque = opaque && (colors[i].GetAlpha() == 0xff); } _transparency = opaque ? Color.OPAQUE : Color.TRANSLUCENT; // check input parameters if (start == null || end == null) { throw new NullReferenceException("Start and end points must be" + "non-null"); } if (start.Equals(end)) { throw new ArgumentException("Start point cannot equal" + "endpoint"); } // copy the points... this._start = new Point(start.GetX(), start.GetY()); this._end = new Point(end.GetX(), end.GetY()); Rectangle rectangle = new Rectangle(start, end); float dx = start.X - end.X; float dy = start.Y - end.Y; double angle = MathEx.Atan2(dy, dx); int intAngle = SingleFP.FromDouble(angle); RectangleFP r = Utils.ToRectangleFP(rectangle); _wrappedBrushFP = new LinearGradientBrushFP(r.GetLeft(), r.GetTop(), r.GetRight(), r.GetBottom(), intAngle); for (int i = 0; i < colors.Length; i++) { ((LinearGradientBrushFP)_wrappedBrushFP).SetGradientColor (SingleFP.FromFloat(fractions[i] / 100.0f), colors[i]._value); } ((LinearGradientBrushFP)_wrappedBrushFP).UpdateGradientTable(); _wrappedBrushFP.SetMatrix(Utils.ToMatrixFP(gradientTransform)); _wrappedBrushFP.FillMode = fillType; }
public LinearGradientBrush(Rectangle rect, Color color1, Color color2, float angle, int fillType) { _start = new Point(rect.X, rect.Y); _end = new Point(rect.X + rect.Width, rect.Y + rect.Height); _gradientTransform = new AffineTransform(); _fractions = new[] { 0, 100 }; _colors = new[] { color1, color2 }; bool opaque = true; for (int i = 0; i < _colors.Length; i++) { opaque = opaque && (_colors[i].GetAlpha() == 0xff); } _transparency = opaque ? Color.OPAQUE : Color.TRANSLUCENT; RectangleFP r = Utils.ToRectangleFP(rect); _wrappedBrushFP = new LinearGradientBrushFP(r.GetLeft(), r.GetTop(), r.GetRight(), r.GetBottom(), MathFP.ToRadians(SingleFP.FromFloat(angle))); for (int i = 0; i < _colors.Length; i++) { ((LinearGradientBrushFP)_wrappedBrushFP) .SetGradientColor(SingleFP.FromFloat(_fractions[i] / 255.0f), _colors[i]._value); } ((LinearGradientBrushFP)_wrappedBrushFP).UpdateGradientTable(); _wrappedBrushFP.SetMatrix(Utils.ToMatrixFP(_gradientTransform)); _wrappedBrushFP.FillMode = fillType; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Constructor. * @param l * @param at */ internal LineIterator(Line l, AffineTransform at) { _line = l; _affine = at; }
internal CubicIterator(CubicCurve q, AffineTransform at) { _cubic = q; _affine = at; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Concatenates an <code>AffineTransform</code> <code>Tx</code> to * this <code>AffineTransform</code> Cx * in a less commonly used way such that <code>Tx</code> modifies the * coordinate transformation relative to the absolute pixel * space rather than relative to the existing user space. * Cx is updated to perform the combined transformation. * Transforming a point p by the updated transform Cx' is * equivalent to first transforming p by the original transform * Cx and then transforming the result by * <code>Tx</code> like this: * Cx'(p) = Tx(Cx(p)) * In matrix notation, if this transform Cx * is represented by the matrix [this] and <code>Tx</code> is * represented by the matrix [Tx] then this method does the * following: * <pre> * [this] = [Tx] x [this] * </pre> * @param Tx the <code>AffineTransform</code> object to be * concatenated with this <code>AffineTransform</code> object. */ public void PreConcatenate(AffineTransform tx) { double m0; double t00, t01, t10, t11; int mystate = _state; int txstate = tx._state; switch ((txstate << HI_SHIFT) | mystate) { case (HI_IDENTITY | APPLY_IDENTITY): case (HI_IDENTITY | APPLY_TRANSLATE): case (HI_IDENTITY | APPLY_SCALE): case (HI_IDENTITY | APPLY_SCALE | APPLY_TRANSLATE): case (HI_IDENTITY | APPLY_SHEAR): case (HI_IDENTITY | APPLY_SHEAR | APPLY_TRANSLATE): case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE): case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): // Tx is IDENTITY... return; case (HI_TRANSLATE | APPLY_IDENTITY): case (HI_TRANSLATE | APPLY_SCALE): case (HI_TRANSLATE | APPLY_SHEAR): case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE): // Tx is TRANSLATE, this has no TRANSLATE _m02 = tx._m02; _m12 = tx._m12; _state = mystate | APPLY_TRANSLATE; _type |= TYPE_TRANSLATION; return; case (HI_TRANSLATE | APPLY_TRANSLATE): case (HI_TRANSLATE | APPLY_SCALE | APPLY_TRANSLATE): case (HI_TRANSLATE | APPLY_SHEAR | APPLY_TRANSLATE): case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): // Tx is TRANSLATE, this has one too _m02 = _m02 + tx._m02; _m12 = _m12 + tx._m12; return; case (HI_SCALE | APPLY_TRANSLATE): case (HI_SCALE | APPLY_IDENTITY): // Only these two existing states need a new state _state = mystate | APPLY_SCALE; t00 = tx._m00; t11 = tx._m11; if ((mystate & APPLY_SHEAR) != 0) { _m01 = _m01 * t00; _m10 = _m10 * t11; if ((mystate & APPLY_SCALE) != 0) { _m00 = _m00 * t00; _m11 = _m11 * t11; } } else { _m00 = _m00 * t00; _m11 = _m11 * t11; } if ((mystate & APPLY_TRANSLATE) != 0) { _m02 = _m02 * t00; _m12 = _m12 * t11; } _type = TYPE_UNKNOWN; return; case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE): case (HI_SCALE | APPLY_SHEAR | APPLY_TRANSLATE): case (HI_SCALE | APPLY_SHEAR): case (HI_SCALE | APPLY_SCALE | APPLY_TRANSLATE): case (HI_SCALE | APPLY_SCALE): // Tx is SCALE, this is anything t00 = tx._m00; t11 = tx._m11; if ((mystate & APPLY_SHEAR) != 0) { _m01 = _m01 * t00; _m10 = _m10 * t11; if ((mystate & APPLY_SCALE) != 0) { _m00 = _m00 * t00; _m11 = _m11 * t11; } } else { _m00 = _m00 * t00; _m11 = _m11 * t11; } if ((mystate & APPLY_TRANSLATE) != 0) { _m02 = _m02 * t00; _m12 = _m12 * t11; } _type = TYPE_UNKNOWN; return; case (HI_SHEAR | APPLY_SHEAR | APPLY_TRANSLATE): case (HI_SHEAR | APPLY_SHEAR): mystate = mystate | APPLY_SCALE; _state = mystate ^ APPLY_SHEAR; // Tx is SHEAR, this is anything t01 = tx._m01; t10 = tx._m10; m0 = _m00; _m00 = _m10 * t01; _m10 = m0 * t10; m0 = _m01; _m01 = _m11 * t01; _m11 = m0 * t10; m0 = _m02; _m02 = _m12 * t01; _m12 = m0 * t10; _type = TYPE_UNKNOWN; return; case (HI_SHEAR | APPLY_TRANSLATE): case (HI_SHEAR | APPLY_IDENTITY): case (HI_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (HI_SHEAR | APPLY_SCALE): _state = mystate ^ APPLY_SHEAR; // Tx is SHEAR, this is anything t01 = tx._m01; t10 = tx._m10; m0 = _m00; _m00 = _m10 * t01; _m10 = m0 * t10; m0 = _m01; _m01 = _m11 * t01; _m11 = m0 * t10; m0 = _m02; _m02 = _m12 * t01; _m12 = m0 * t10; _type = TYPE_UNKNOWN; return; case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE): // Tx is SHEAR, this is anything t01 = tx._m01; t10 = tx._m10; m0 = _m00; _m00 = _m10 * t01; _m10 = m0 * t10; m0 = _m01; _m01 = _m11 * t01; _m11 = m0 * t10; m0 = _m02; _m02 = _m12 * t01; _m12 = m0 * t10; _type = TYPE_UNKNOWN; return; } // If Tx has more than one attribute, it is not worth optimizing // all of those cases... t00 = tx._m00; t01 = tx._m01; double t02 = tx._m02; t10 = tx._m10; t11 = tx._m11; double t12 = tx._m12; switch (mystate) { default: StateError(); break; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): m0 = _m02; double m1 = _m12; t02 += m0 * t00 + m1 * t01; t12 += m0 * t10 + m1 * t11; _m02 = t02; _m12 = t12; m0 = _m00; m1 = _m10; _m00 = m0 * t00 + m1 * t01; _m10 = m0 * t10 + m1 * t11; m0 = _m01; m1 = _m11; _m01 = m0 * t00 + m1 * t01; _m11 = m0 * t10 + m1 * t11; break; case (APPLY_SHEAR | APPLY_SCALE): _m02 = t02; _m12 = t12; m0 = _m00; m1 = _m10; _m00 = m0 * t00 + m1 * t01; _m10 = m0 * t10 + m1 * t11; m0 = _m01; m1 = _m11; _m01 = m0 * t00 + m1 * t01; _m11 = m0 * t10 + m1 * t11; break; case (APPLY_SHEAR | APPLY_TRANSLATE): m0 = _m02; m1 = _m12; t02 += m0 * t00 + m1 * t01; t12 += m0 * t10 + m1 * t11; _m02 = t02; _m12 = t12; m0 = _m10; _m00 = m0 * t01; _m10 = m0 * t11; m0 = _m01; _m01 = m0 * t00; _m11 = m0 * t10; break; case (APPLY_SHEAR): _m02 = t02; _m12 = t12; m0 = _m10; _m00 = m0 * t01; _m10 = m0 * t11; m0 = _m01; _m01 = m0 * t00; _m11 = m0 * t10; break; case (APPLY_SCALE | APPLY_TRANSLATE): m0 = _m02; m1 = _m12; t02 += m0 * t00 + m1 * t01; t12 += m0 * t10 + m1 * t11; _m02 = t02; _m12 = t12; m0 = _m00; _m00 = m0 * t00; _m10 = m0 * t10; m0 = _m11; _m01 = m0 * t01; _m11 = m0 * t11; break; case (APPLY_SCALE): _m02 = t02; _m12 = t12; m0 = _m00; _m00 = m0 * t00; _m10 = m0 * t10; m0 = _m11; _m01 = m0 * t01; _m11 = m0 * t11; break; case (APPLY_TRANSLATE): m0 = _m02; m1 = _m12; t02 += m0 * t00 + m1 * t01; t12 += m0 * t10 + m1 * t11; _m02 = t02; _m12 = t12; _m00 = t00; _m10 = t10; _m01 = t01; _m11 = t11; _state = mystate | txstate; _type = TYPE_UNKNOWN; return; case (APPLY_IDENTITY): _m02 = t02; _m12 = t12; _m00 = t00; _m10 = t10; _m01 = t01; _m11 = t11; _state = mystate | txstate; _type = TYPE_UNKNOWN; return; } UpdateState(); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns an iteration object that defines the boundary of the * flattened shape of this <code>QuadCurve</code>. * The iterator for this class is not multi-threaded safe, * which means that this <code>QuadCurve</code> class does not * guarantee that modifications to the geometry of this * <code>QuadCurve</code> object do not affect any iterations of * that geometry that are already in process. * @param at an optional <code>AffineTransform</code> to apply * to the boundary of the shape * @param flatness the maximum distance that the control points for a * subdivided curve can be with respect to a line connecting * the end points of this curve before this curve is * replaced by a straight line connecting the end points. * @return a <code>PathIterator</code> object that defines the * flattened boundary of the shape. */ public PathIterator GetPathIterator(AffineTransform at, int flatness) { return new FlatteningPathIterator(GetPathIterator(at), flatness); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns a transform that rotates coordinates by the specified * number of quadrants around the specified anchor point. * This operation is equivalent to calling: * <pre> * AffineTransform.getRotateInstance(numquadrants * Math.PI / 2.0, * anchorx, anchory); * </pre> * Rotating by a positive number of quadrants rotates points on * the positive X axis toward the positive Y axis. * * @param numquadrants the number of 90 degree arcs to rotate by * @param anchorx the X coordinate of the rotation anchor point * @param anchory the Y coordinate of the rotation anchor point * @return an <code>AffineTransform</code> object that rotates * coordinates by the specified number of quadrants around the * specified anchor point. */ public static AffineTransform GetQuadrantRotateInstance(int numquadrants, double anchorx, double anchory) { var tx = new AffineTransform(); tx.SetToQuadrantRotation(numquadrants, anchorx, anchory); return tx; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns an iterator object that iterates along the boundary of this * <code>Polygon</code> and provides access to the geometry * of the outline of this <code>Polygon</code>. An optional * {@link AffineTransform} can be specified so that the coordinates * returned in the iteration are transformed accordingly. * @param at an optional <code>AffineTransform</code> to be applied to the * coordinates as they are returned in the iteration, or * <code>null</code> if untransformed coordinates are desired * @return a {@link IPathIterator} object that provides access to the * geometry of this <code>Polygon</code>. */ public PathIterator GetPathIterator(AffineTransform at) { return new PolygonPathIterator(this, at); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns a transform that rotates coordinates around an anchor * point accordinate to a rotation vector. * All coordinates rotate about the specified anchor coordinates * by the same amount. * The amount of rotation is such that coordinates along the former * positive X axis will subsequently align with the vector pointing * from the origin to the specified vector coordinates. * If both <code>vecx</code> and <code>vecy</code> are 0.0, * an identity transform is returned. * This operation is equivalent to calling: * <pre> * AffineTransform.getRotateInstance(Math.Atan2(vecy, vecx), * anchorx, anchory); * </pre> * * @param vecx the X coordinate of the rotation vector * @param vecy the Y coordinate of the rotation vector * @param anchorx the X coordinate of the rotation anchor point * @param anchory the Y coordinate of the rotation anchor point * @return an <code>AffineTransform</code> object that rotates * coordinates around the specified point according to the * specified rotation vector. */ public static AffineTransform GetRotateInstance(double vecx, double vecy, double anchorx, double anchory) { var tx = new AffineTransform(); tx.SetToRotation(vecx, vecy, anchorx, anchory); return tx; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns an iterator object that iterates along the boundary of * the <code>IShape</code> and provides access to the geometry of the * outline of the <code>IShape</code>. Only SEG_MOVETO, SEG_LINETO, and * SEG_CLOSE point types are returned by the iterator. * Since polygons are already flat, the <code>flatness</code> parameter * is ignored. An optional <code>AffineTransform</code> can be specified * in which case the coordinates returned in the iteration are transformed * accordingly. * @param at an optional <code>AffineTransform</code> to be applied to the * coordinates as they are returned in the iteration, or * <code>null</code> if untransformed coordinates are desired * @param flatness the maximum amount that the control points * for a given curve can vary from colinear before a subdivided * curve is replaced by a straight line connecting the * endpoints. Since polygons are already flat the * <code>flatness</code> parameter is ignored. * @return a <code>IPathIterator</code> object that provides access to the * <code>IShape</code> object's geometry. */ public PathIterator GetPathIterator(AffineTransform at, int flatness) { return GetPathIterator(at); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns a transform representing a shearing transformation. * The matrix representing the returned transform is: * <pre> * [ 1 shx 0 ] * [ shy 1 0 ] * [ 0 0 1 ] * </pre> * @param shx the multiplier by which coordinates are shifted in the * direction of the positive X axis as a factor of their Y coordinate * @param shy the multiplier by which coordinates are shifted in the * direction of the positive Y axis as a factor of their X coordinate * @return an <code>AffineTransform</code> object that shears * coordinates by the specified multipliers. */ public static AffineTransform GetShearInstance(double shx, double shy) { var tx = new AffineTransform(); tx.SetToShear(shx, shy); return tx; }
public PolygonPathIterator(Polygon pg, AffineTransform at) { poly = pg; transform = at; if (pg.NumOfNpoints == 0) { // Prevent a spurious SEG_CLOSE segment index = 1; } }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Concatenates an <code>AffineTransform</code> <code>Tx</code> to * this <code>AffineTransform</code> Cx in the most commonly useful * way to provide a new user space * that is mapped to the former user space by <code>Tx</code>. * Cx is updated to perform the combined transformation. * Transforming a point p by the updated transform Cx' is * equivalent to first transforming p by <code>Tx</code> and then * transforming the result by the original transform Cx like this: * Cx'(p) = Cx(Tx(p)) * In matrix notation, if this transform Cx is * represented by the matrix [this] and <code>Tx</code> is represented * by the matrix [Tx] then this method does the following: * <pre> * [this] = [this] x [Tx] * </pre> * @param Tx the <code>AffineTransform</code> object to be * concatenated with this <code>AffineTransform</code> object. */ public void Concatenate(AffineTransform tx) { double m0, m1; double t01, t10; int mystate = _state; int txstate = tx._state; switch ((txstate << HI_SHIFT) | mystate) { /* ---------- Tx == IDENTITY cases ---------- */ case (HI_IDENTITY | APPLY_IDENTITY): case (HI_IDENTITY | APPLY_TRANSLATE): case (HI_IDENTITY | APPLY_SCALE): case (HI_IDENTITY | APPLY_SCALE | APPLY_TRANSLATE): case (HI_IDENTITY | APPLY_SHEAR): case (HI_IDENTITY | APPLY_SHEAR | APPLY_TRANSLATE): case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE): case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): return; /* ---------- this == IDENTITY cases ---------- */ case (HI_SHEAR | HI_SCALE | HI_TRANSLATE | APPLY_IDENTITY): _m01 = tx._m01; _m10 = tx._m10; _m00 = tx._m00; _m11 = tx._m11; _m02 = tx._m02; _m12 = tx._m12; _state = txstate; _type = tx._type; return; case (HI_SCALE | HI_TRANSLATE | APPLY_IDENTITY): _m00 = tx._m00; _m11 = tx._m11; _m02 = tx._m02; _m12 = tx._m12; _state = txstate; _type = tx._type; return; case (HI_TRANSLATE | APPLY_IDENTITY): _m02 = tx._m02; _m12 = tx._m12; _state = txstate; _type = tx._type; return; case (HI_SHEAR | HI_SCALE | APPLY_IDENTITY): _m01 = tx._m01; _m10 = tx._m10; _m00 = tx._m00; _m11 = tx._m11; _state = txstate; _type = tx._type; return; case (HI_SCALE | APPLY_IDENTITY): _m00 = tx._m00; _m11 = tx._m11; _state = txstate; _type = tx._type; return; case (HI_SHEAR | HI_TRANSLATE | APPLY_IDENTITY): _m02 = tx._m02; _m12 = tx._m12; _m01 = tx._m01; _m10 = tx._m10; _m00 = _m11 = 0.0; _state = txstate; _type = tx._type; return; case (HI_SHEAR | APPLY_IDENTITY): _m01 = tx._m01; _m10 = tx._m10; _m00 = _m11 = 0.0; _state = txstate; _type = tx._type; return; /* ---------- Tx == TRANSLATE cases ---------- */ case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE): case (HI_TRANSLATE | APPLY_SHEAR | APPLY_TRANSLATE): case (HI_TRANSLATE | APPLY_SHEAR): case (HI_TRANSLATE | APPLY_SCALE | APPLY_TRANSLATE): case (HI_TRANSLATE | APPLY_SCALE): case (HI_TRANSLATE | APPLY_TRANSLATE): Translate(tx._m02, tx._m12); return; /* ---------- Tx == SCALE cases ---------- */ case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE): case (HI_SCALE | APPLY_SHEAR | APPLY_TRANSLATE): case (HI_SCALE | APPLY_SHEAR): case (HI_SCALE | APPLY_SCALE | APPLY_TRANSLATE): case (HI_SCALE | APPLY_SCALE): case (HI_SCALE | APPLY_TRANSLATE): Scale(tx._m00, tx._m11); return; /* ---------- Tx == SHEAR cases ---------- */ case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE): t01 = tx._m01; t10 = tx._m10; m0 = _m00; _m00 = _m01 * t10; _m01 = m0 * t01; m0 = _m10; _m10 = _m11 * t10; _m11 = m0 * t01; _type = TYPE_UNKNOWN; return; case (HI_SHEAR | APPLY_SHEAR | APPLY_TRANSLATE): case (HI_SHEAR | APPLY_SHEAR): _m00 = _m01 * tx._m10; _m01 = 0.0; _m11 = _m10 * tx._m01; _m10 = 0.0; _state = mystate ^ (APPLY_SHEAR | APPLY_SCALE); _type = TYPE_UNKNOWN; return; case (HI_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (HI_SHEAR | APPLY_SCALE): _m01 = _m00 * tx._m01; _m00 = 0.0; _m10 = _m11 * tx._m10; _m11 = 0.0; _state = mystate ^ (APPLY_SHEAR | APPLY_SCALE); _type = TYPE_UNKNOWN; return; case (HI_SHEAR | APPLY_TRANSLATE): _m00 = 0.0; _m01 = tx._m01; _m10 = tx._m10; _m11 = 0.0; _state = APPLY_TRANSLATE | APPLY_SHEAR; _type = TYPE_UNKNOWN; return; } // If Tx has more than one attribute, it is not worth optimizing // all of those cases... double t00 = tx._m00; t01 = tx._m01; double t02 = tx._m02; t10 = tx._m10; double t11 = tx._m11; double t12 = tx._m12; switch (mystate) { default: StateError(); return; case (APPLY_SHEAR | APPLY_SCALE): _state = mystate | txstate; m0 = _m00; m1 = _m01; _m00 = t00 * m0 + t10 * m1; _m01 = t01 * m0 + t11 * m1; _m02 += t02 * m0 + t12 * m1; m0 = _m10; m1 = _m11; _m10 = t00 * m0 + t10 * m1; _m11 = t01 * m0 + t11 * m1; _m12 += t02 * m0 + t12 * m1; _type = TYPE_UNKNOWN; return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): m0 = _m00; m1 = _m01; _m00 = t00 * m0 + t10 * m1; _m01 = t01 * m0 + t11 * m1; _m02 += t02 * m0 + t12 * m1; m0 = _m10; m1 = _m11; _m10 = t00 * m0 + t10 * m1; _m11 = t01 * m0 + t11 * m1; _m12 += t02 * m0 + t12 * m1; _type = TYPE_UNKNOWN; return; case (APPLY_SHEAR | APPLY_TRANSLATE): case (APPLY_SHEAR): m0 = _m01; _m00 = t10 * m0; _m01 = t11 * m0; _m02 += t12 * m0; m0 = _m10; _m10 = t00 * m0; _m11 = t01 * m0; _m12 += t02 * m0; break; case (APPLY_SCALE | APPLY_TRANSLATE): case (APPLY_SCALE): m0 = _m00; _m00 = t00 * m0; _m01 = t01 * m0; _m02 += t02 * m0; m0 = _m11; _m10 = t10 * m0; _m11 = t11 * m0; _m12 += t12 * m0; break; case (APPLY_TRANSLATE): _m00 = t00; _m01 = t01; _m02 += t02; _m10 = t10; _m11 = t11; _m12 += t12; _state = txstate | APPLY_TRANSLATE; _type = TYPE_UNKNOWN; return; } UpdateState(); }
// Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 15JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Constructs a {@code RadialGradientBrush}. * * @param center the center point in user space of the circle defining the * gradient. The last color of the gradient is mapped to * the perimeter of this circle. * @param radius the radius of the circle defining the extents of the * color gradient * @param fractions numbers ranging from 0.0 to 1.0 specifying the * distribution of colors along the gradient * @param colors array of colors to use in the gradient. The first color * is used at the focus point, the last color around the * perimeter of the circle. * @param fillType either {@code NO_CYCLE}, {@code REFLECT}, * or {@code REPEAT} * @param gradientTransform transform to apply to the gradient * * @throws NullPointerException * if one of the points is null, * or {@code fractions} array is null, * or {@code colors} array is null, * or {@code cycleMethod} is null, * or {@code colorSpace} is null, * or {@code gradientTransform} is null * @throws IllegalArgumentException * if {@code radius} is non-positive, * or {@code fractions.length != colors.length}, * or {@code colors} is less than 2 in size, * or a {@code fractions} Value is less than 0.0 or greater than 1.0, * or the {@code fractions} are not provided in strictly increasing order */ public RadialGradientBrush(Point center, int radius, int[] fractions, Color[] colors, int fillType, AffineTransform gradientTransform) { if (fractions == null) { throw new NullReferenceException("Fractions array cannot be null"); } if (colors == null) { throw new NullReferenceException("Colors array cannot be null"); } if (gradientTransform == null) { throw new NullReferenceException("Gradient transform cannot be " + "null"); } if (fractions.Length != colors.Length) { throw new ArgumentException("Colors and fractions must " + "have equal size"); } if (colors.Length < 2) { throw new ArgumentException("User must specify at least " + "2 colors"); } // check that values are in the proper range and progress // in increasing order from 0 to 1 int previousFraction = -255; for (int i = 0; i < fractions.Length; i++) { int currentFraction = fractions[i]; if (currentFraction < 0 || currentFraction > 255) { throw new ArgumentException("Fraction values must " + "be in the range 0 to 255: " + currentFraction); } if (currentFraction <= previousFraction) { throw new ArgumentException("Keyframe fractions " + "must be increasing: " + currentFraction); } previousFraction = currentFraction; } // We have to deal with the cases where the first gradient stop is not // equal to 0 and/or the last gradient stop is not equal to 1. // In both cases, create a new point and replicate the previous // extreme point's color. bool fixFirst = false; bool fixLast = false; int len = fractions.Length; int off = 0; if (fractions[0] != 0) { // first stop is not equal to zero, fix this condition fixFirst = true; len++; off++; } if (fractions[fractions.Length - 1] != 255) { // last stop is not equal to one, fix this condition fixLast = true; len++; } _fractions = new int[len]; Array.Copy(fractions, 0, _fractions, off, fractions.Length); _colors = new Color[len]; Array.Copy(colors, 0, _colors, off, colors.Length); if (fixFirst) { _fractions[0] = 0; _colors[0] = colors[0]; } if (fixLast) { _fractions[len - 1] = 255; _colors[len - 1] = colors[colors.Length - 1]; } // copy the gradient transform _gradientTransform = new AffineTransform(gradientTransform); // determine transparency bool opaque = true; for (int i = 0; i < colors.Length; i++) { opaque = opaque && (colors[i].GetAlpha() == 0xff); } _transparency = opaque ? Color.OPAQUE : Color.TRANSLUCENT; // check input arguments if (center == null) { throw new NullReferenceException("Center point must be non-null"); } if (radius <= 0) { throw new ArgumentException("Radius must be greater " + "than zero"); } // copy parameters _center = new Point(center.X, center.Y); _radius = radius; _fillType = fillType; _wrappedBrushFP = new RadialGradientBrushFP(SingleFP.FromInt(center.X), SingleFP.FromInt(center.Y), SingleFP.FromInt(radius), 0); for (int i = 0; i < colors.Length; i++) { ((RadialGradientBrushFP)_wrappedBrushFP).SetGradientColor(SingleFP.FromFloat(fractions[i] / 100.0f), colors[i]._value); } ((RadialGradientBrushFP)_wrappedBrushFP).UpdateGradientTable(); _wrappedBrushFP.SetMatrix(Utils.ToMatrixFP(gradientTransform)); _wrappedBrushFP.FillMode = fillType; }