2 // System.Drawing.Pen.cs
5 // Miguel de Icaza (miguel@ximian.com)
6 // Alexandre Pigolkine (pigolkine@gmx.de)
7 // Duncan Mak (duncan@ximian.com)
8 // Ravindra (rkumar@novell.com)
10 // (C) Ximian, Inc. http://www.ximian.com
11 // (C) Novell, Inc. http://www.novell.com
15 using System.Drawing.Drawing2D;
16 using System.Runtime.InteropServices;
19 using geom = java.awt.geom;
21 namespace System.Drawing
\r
24 public sealed class Pen : MarshalByRefObject, ICloneable, IDisposable, awt.Stroke
\r
28 static readonly float [] DASH_ARRAY = {4.0f,1.0f};
29 static readonly float [] DASHDOT_ARRAY = {4.0f,1.0f,1.0f,1.0f};
30 static readonly float [] DASHDOTDOT_ARRAY = {4.0f,1.0f,1.0f,1.0f,1.0f,1.0f};
31 static readonly float [] DOT_ARRAY = {1.0f,1.0f};
33 internal bool isModifiable = true;
43 PenAlignment _alignment;
48 //float[] _compoundArray;
54 #region Ctors. and Dtor
56 public Pen (Brush brush) : this (brush, 1.0F)
59 public Pen (Color color) : this (color, 1.0F)
62 public Pen (Color color, float width) : this(new SolidBrush(color), width)
65 public Pen (Brush brush, float width)
67 _brush = (Brush)brush.Clone();;
69 _dashStyle = DashStyle.Solid;
70 _startCap = LineCap.Flat;
71 _dashCap = DashCap.Flat;
72 _endCap = LineCap.Flat;
73 _alignment = PenAlignment.Center;
74 _lineJoin = LineJoin.Miter;
76 _transform = new Matrix();
82 #region Alignment [TODO]
83 public PenAlignment Alignment
\r
110 throw new ArgumentNullException("brush");
117 public Color Color
\r
121 if(Brush is SolidBrush)
122 return ((SolidBrush)Brush).Color;
123 else if(Brush is HatchBrush)
124 return ((HatchBrush)Brush).ForegroundColor;
132 _brush = new SolidBrush (value);
137 #region CompoundArray [TODO]
138 public float[] CompoundArray {
140 throw new NotImplementedException ();
143 throw new NotImplementedException ();
148 #region CustomEndCap [TODO]
149 public CustomLineCap CustomEndCap
\r
153 throw new NotImplementedException ();
155 // do a check for isModifiable when implementing this property
158 throw new NotImplementedException ();
163 #region CustomStartCap [TODO]
164 public CustomLineCap CustomStartCap
\r
169 throw new NotImplementedException ();
172 // do a check for isModifiable when implementing this property
175 throw new NotImplementedException ();
181 public DashCap DashCap {
194 public float DashOffset
\r
212 public float [] DashPattern
\r
223 _dashPattern = value;
224 DashStyle = (_dashPattern == null) ? DashStyle.Solid : DashStyle.Custom;
230 public DashStyle DashStyle
\r
245 #region StartCap [TODO - now allways endcap]
247 public LineCap StartCap {
260 public LineCap EndCap
\r
276 #region LineJoin [partial TODO - missed styles]
277 public LineJoin LineJoin {
291 public float MiterLimit
\r
310 public PenType PenType
\r
314 if (Brush is TextureBrush)
315 return PenType.TextureFill;
316 else if (Brush is HatchBrush)
317 return PenType.HatchFill;
318 else if (Brush is LinearGradientBrush)
319 return PenType.LinearGradient;
320 else if (Brush is PathGradientBrush)
321 return PenType.PathGradient;
323 return PenType.SolidColor;
329 public Matrix Transform
\r
333 return _transform.Clone();
340 value.CopyTo(_transform);
346 public float Width
\r
362 public object Clone ()
364 Pen clone = (Pen)MemberwiseClone();
365 if (clone._transform != null)
366 clone._transform = clone._transform.Clone();
367 if (clone._dashPattern != null)
368 clone._dashPattern = (float[])clone._dashPattern.Clone();
374 public void Dispose ()
378 void Dispose (bool disposing)
380 if (!isModifiable && disposing)
381 throw new ArgumentException ("You may not change this Pen because it does not belong to you.");
382 // Restore the dtor if adding anything below
386 #region Transform Funcs
387 public void MultiplyTransform (Matrix matrix)
389 _transform.Multiply (matrix);
392 public void MultiplyTransform (Matrix matrix, MatrixOrder order)
394 _transform.Multiply (matrix, order);
397 public void ResetTransform ()
402 public void RotateTransform (float angle)
404 _transform.Rotate (angle);
407 public void RotateTransform (float angle, MatrixOrder order)
409 _transform.Rotate (angle, order);
412 public void ScaleTransform (float sx, float sy)
414 _transform.Scale (sx, sy);
417 public void ScaleTransform (float sx, float sy, MatrixOrder order)
419 _transform.Scale (sx, sy, order);
422 public void TranslateTransform (float dx, float dy) {
423 _transform.Translate (dx, dy);
426 public void TranslateTransform (float dx, float dy, MatrixOrder order) {
427 _transform.Translate (dx, dy, order);
431 public void SetLineCap (LineCap startCap, LineCap endCap, DashCap dashCap)
438 void EnsureModifiable() {
440 throw new ArgumentException ("You may not change this Pen because it does not belong to you.");
443 internal double GetSquaredTransformedWidth(geom.AffineTransform coordsTransform) {
444 geom.AffineTransform transform = _transform.NativeObject;
445 double A = transform.getScaleX(); // m00
446 double B = transform.getShearY(); // m10
447 double C = transform.getShearX(); // m01
448 double D = transform.getScaleY(); // m11
450 double K = coordsTransform.getScaleX(); // m00
451 double L = coordsTransform.getShearY(); // m10
452 double M = coordsTransform.getShearX(); // m01
453 double N = coordsTransform.getScaleY(); // m11
455 double AD = A*D, BC = B*C, KN = K*N, LM = L*M;
456 double KN_LM = KN-LM;
457 return Math.Abs(Width*Width * (AD*KN_LM - BC*KN_LM));
460 internal awt.Stroke GetNativeObject(geom.AffineTransform outputTransform, bool fitPen) {
461 return GetNativeObject(null, outputTransform, fitPen);
466 /// <param name="outputTransform">transform which will be applied on the final shape</param>
\r
467 /// <param name="fitPen">ensure the shape will wide enough to be visible</param>
\r
468 /// <returns></returns>
469 internal awt.Stroke GetNativeObject(geom.AffineTransform penTransform, geom.AffineTransform outputTransform, bool fitPen) {
470 float[] dashPattern = null;
\r
472 switch (DashStyle) {
\r
473 case DashStyle.Custom:
\r
474 if (DashPattern != null) {
\r
475 dashPattern = new float[DashPattern.Length];
\r
476 for(int i = 0; i < DashPattern.Length; i++) {
478 if (EndCap == LineCap.Flat)
479 dashPattern[i] = DashPattern[i] * Width;
482 // remove the size of caps from the opaque parts
483 dashPattern[i] = (DashPattern[i] * Width) - Width;
485 // add the size of caps to the transparent parts
486 dashPattern[i] = (DashPattern[i] * Width) + Width;
491 case DashStyle.Dash:
\r
492 dashPattern = DASH_ARRAY;
\r
494 case DashStyle.DashDot:
\r
495 dashPattern = DASHDOT_ARRAY;
\r
497 case DashStyle.DashDotDot:
\r
498 dashPattern = DASHDOTDOT_ARRAY;
\r
502 // case DashStyle.Solid:
\r
509 join = java.awt.BasicStroke.JOIN_BEVEL;
513 case LineJoin.MiterClipped:
514 join = java.awt.BasicStroke.JOIN_MITER;
517 join = java.awt.BasicStroke.JOIN_ROUND;
\r
521 // We go by End cap for now.
\r
526 case LineCap.SquareAnchor:
527 cap = awt.BasicStroke.CAP_SQUARE;
530 case LineCap.RoundAnchor:
531 cap = awt.BasicStroke.CAP_ROUND;
534 cap = awt.BasicStroke.CAP_BUTT;
538 geom.AffineTransform penT = _transform.NativeObject;
\r
539 if (penTransform != null && !penTransform.isIdentity()) {
\r
540 penT = (geom.AffineTransform)penT.clone();
\r
541 penT.concatenate(penTransform);
\r
544 return StrokeFactory.CreateStroke(Width, cap,
\r
545 join, MiterLimit, dashPattern, DashOffset,
\r
546 penT, outputTransform, fitPen);
549 #region Stroke Members
\r
551 awt.Shape awt.Stroke.createStrokedShape(awt.Shape arg_0) {
\r
552 return GetNativeObject(null, false).createStrokedShape(arg_0);
\r