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
24 public sealed class Pen
: MarshalByRefObject
, ICloneable
, IDisposable
, awt
.Stroke
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
110 throw new ArgumentNullException("brush");
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]
139 public float[] CompoundArray
{
141 throw new NotImplementedException ();
144 throw new NotImplementedException ();
149 #region CustomEndCap [TODO]
151 public CustomLineCap CustomEndCap
155 throw new NotImplementedException ();
157 // do a check for isModifiable when implementing this property
160 throw new NotImplementedException ();
165 #region CustomStartCap [TODO]
167 public CustomLineCap CustomStartCap
171 throw new NotImplementedException ();
174 // do a check for isModifiable when implementing this property
177 throw new NotImplementedException ();
184 public DashCap DashCap
{
197 public float DashOffset
215 public float [] DashPattern
219 return (float [])_dashPattern
.Clone();
226 _dashPattern
= value;
227 DashStyle
= (_dashPattern
== null) ? DashStyle
.Solid
: DashStyle
.Custom
;
233 public DashStyle DashStyle
248 #region StartCap [TODO - now allways endcap]
250 public LineCap StartCap
{
264 public LineCap EndCap
280 #region LineJoin [partial TODO - missed styles]
282 public LineJoin LineJoin
{
296 public float MiterLimit
315 public PenType PenType
319 if (Brush
is TextureBrush
)
320 return PenType
.TextureFill
;
321 else if (Brush
is HatchBrush
)
322 return PenType
.HatchFill
;
323 else if (Brush
is LinearGradientBrush
)
324 return PenType
.LinearGradient
;
325 else if (Brush
is PathGradientBrush
)
326 return PenType
.PathGradient
;
328 return PenType
.SolidColor
;
334 public Matrix Transform
338 return _transform
.Clone();
345 value.CopyTo(_transform
);
367 public object Clone ()
369 Pen clone
= (Pen
)MemberwiseClone();
370 if (clone
._transform
!= null)
371 clone
._transform
= clone
._transform
.Clone();
372 if (clone
._dashPattern
!= null)
373 clone
._dashPattern
= (float[])clone
._dashPattern
.Clone();
379 public void Dispose ()
383 void Dispose (bool disposing
)
385 if (!isModifiable
&& disposing
)
386 throw new ArgumentException ("You may not change this Pen because it does not belong to you.");
387 // Restore the dtor if adding anything below
391 #region Transform Funcs
392 public void MultiplyTransform (Matrix matrix
)
394 _transform
.Multiply (matrix
);
397 public void MultiplyTransform (Matrix matrix
, MatrixOrder order
)
399 _transform
.Multiply (matrix
, order
);
402 public void ResetTransform ()
407 public void RotateTransform (float angle
)
409 _transform
.Rotate (angle
);
412 public void RotateTransform (float angle
, MatrixOrder order
)
414 _transform
.Rotate (angle
, order
);
417 public void ScaleTransform (float sx
, float sy
)
419 _transform
.Scale (sx
, sy
);
422 public void ScaleTransform (float sx
, float sy
, MatrixOrder order
)
424 _transform
.Scale (sx
, sy
, order
);
427 public void TranslateTransform (float dx
, float dy
) {
428 _transform
.Translate (dx
, dy
);
431 public void TranslateTransform (float dx
, float dy
, MatrixOrder order
) {
432 _transform
.Translate (dx
, dy
, order
);
436 public void SetLineCap (LineCap startCap
, LineCap endCap
, DashCap dashCap
)
443 void EnsureModifiable() {
445 throw new ArgumentException ("You may not change this Pen because it does not belong to you.");
448 internal double GetSquaredTransformedWidth(geom
.AffineTransform coordsTransform
) {
449 geom
.AffineTransform transform
= _transform
.NativeObject
;
450 double A
= transform
.getScaleX(); // m00
451 double B
= transform
.getShearY(); // m10
452 double C
= transform
.getShearX(); // m01
453 double D
= transform
.getScaleY(); // m11
455 double K
= coordsTransform
.getScaleX(); // m00
456 double L
= coordsTransform
.getShearY(); // m10
457 double M
= coordsTransform
.getShearX(); // m01
458 double N
= coordsTransform
.getScaleY(); // m11
460 double AD
= A
*D
, BC
= B
*C
, KN
= K
*N
, LM
= L
*M
;
461 double KN_LM
= KN
-LM
;
462 return Math
.Abs(Width
*Width
* (AD
*KN_LM
- BC
*KN_LM
));
466 internal bool CanCreateBasicStroke
{
468 if (!_transform
.IsIdentity
)
471 //FIXME: add more logic when more features will
477 internal awt
.Stroke
GetNativeObject(geom
.AffineTransform outputTransform
, PenFit penFit
) {
478 return GetNativeObject(null, outputTransform
, penFit
);
483 /// <param name="outputTransform">transform which will be applied on the final shape</param>
484 /// <param name="fitPen">ensure the shape will wide enough to be visible</param>
485 /// <returns></returns>
486 internal awt
.Stroke
GetNativeObject(geom
.AffineTransform penTransform
, geom
.AffineTransform outputTransform
, PenFit penFit
) {
487 float[] dashPattern
= null;
490 case DashStyle
.Custom
:
491 if (_dashPattern
!= null) {
492 dashPattern
= new float[_dashPattern
.Length
];
493 for(int i
= 0; i
< _dashPattern
.Length
; i
++) {
495 if (EndCap
== LineCap
.Flat
)
496 dashPattern
[i
] = _dashPattern
[i
] * Width
;
499 // remove the size of caps from the opaque parts
500 dashPattern
[i
] = (_dashPattern
[i
] * Width
) - Width
;
501 if (_dashPattern
[i
] < 0)
505 // add the size of caps to the transparent parts
506 dashPattern
[i
] = (_dashPattern
[i
] * Width
) + Width
;
512 dashPattern
= DASH_ARRAY
;
514 case DashStyle
.DashDot
:
515 dashPattern
= DASHDOT_ARRAY
;
517 case DashStyle
.DashDotDot
:
518 dashPattern
= DASHDOTDOT_ARRAY
;
522 // case DashStyle.Solid:
529 join = java
.awt
.BasicStroke
.JOIN_BEVEL
;
533 case LineJoin
.MiterClipped
:
534 join = java
.awt
.BasicStroke
.JOIN_MITER
;
537 join = java
.awt
.BasicStroke
.JOIN_ROUND
;
541 // We go by End cap for now.
546 case LineCap
.SquareAnchor
:
547 cap
= awt
.BasicStroke
.CAP_SQUARE
;
550 case LineCap
.RoundAnchor
:
551 cap
= awt
.BasicStroke
.CAP_ROUND
;
554 cap
= awt
.BasicStroke
.CAP_BUTT
;
558 geom
.AffineTransform penT
= _transform
.NativeObject
;
559 if (penTransform
!= null && !penTransform
.isIdentity()) {
560 penT
= (geom
.AffineTransform
) penT
.clone();
561 penT
.concatenate(penTransform
);
564 return StrokeFactory
.CreateStroke(Width
, cap
,
565 join, MiterLimit
, dashPattern
, DashOffset
,
566 penT
, outputTransform
, penFit
);
569 #region Stroke Members
571 awt
.Shape awt
.Stroke
.createStrokedShape(awt
.Shape arg_0
) {
572 return GetNativeObject(null, PenFit
.NotThin
).createStrokedShape(arg_0
);