2010-04-07 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.Drawing / System.Drawing / Pen.jvm.cs
blobbd9ca2b298a684593a3e97c4440fb5a21e8e837e
1 //
2 // System.Drawing.Pen.cs
3 //
4 // Authors:
5 // Miguel de Icaza (miguel@ximian.com)
6 // Alexandre Pigolkine (pigolkine@gmx.de)
7 // Duncan Mak (duncan@ximian.com)
8 // Ravindra (rkumar@novell.com)
9 //
10 // (C) Ximian, Inc. http://www.ximian.com
11 // (C) Novell, Inc. http://www.novell.com
14 using System;
15 using System.Drawing.Drawing2D;
16 using System.Runtime.InteropServices;
18 using awt = java.awt;
19 using geom = java.awt.geom;
21 namespace System.Drawing
24 public sealed class Pen : MarshalByRefObject, ICloneable, IDisposable, awt.Stroke
26 #region Member Vars
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;
35 Brush _brush;
36 DashStyle _dashStyle;
37 DashCap _dashCap;
38 LineCap _startCap;
39 LineCap _endCap;
41 LineJoin _lineJoin;
43 PenAlignment _alignment;
44 Matrix _transform;
45 float _width;
46 float _dashOffset;
47 float[] _dashPattern;
48 //float[] _compoundArray;
50 float _miterLimit;
52 #endregion
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();;
68 _width = width;
69 _dashStyle = DashStyle.Solid;
70 _startCap = LineCap.Flat;
71 _dashCap = DashCap.Flat;
72 _endCap = LineCap.Flat;
73 _alignment = PenAlignment.Center;
74 _lineJoin = LineJoin.Miter;
75 _miterLimit = 10f;
76 _transform = new Matrix();
78 #endregion
80 // Properties
82 #region Alignment [TODO]
83 public PenAlignment Alignment
85 get
87 return _alignment;
90 set
92 EnsureModifiable();
93 _alignment = value;
96 #endregion
98 #region Brush
99 public Brush Brush
101 get
103 return _brush;
106 set
108 EnsureModifiable();
109 if (value == null)
110 throw new ArgumentNullException("brush");
111 _brush = value;
114 #endregion
116 #region Color
117 public Color Color
119 get
121 if(Brush is SolidBrush)
122 return ((SolidBrush)Brush).Color;
123 else if(Brush is HatchBrush)
124 return ((HatchBrush)Brush).ForegroundColor;
125 else
126 return Color.Empty;
129 set
131 EnsureModifiable();
132 _brush = new SolidBrush (value);
135 #endregion
137 #region CompoundArray [TODO]
138 [MonoTODO]
139 public float[] CompoundArray {
140 get {
141 throw new NotImplementedException ();
143 set {
144 throw new NotImplementedException ();
147 #endregion
149 #region CustomEndCap [TODO]
150 [MonoTODO]
151 public CustomLineCap CustomEndCap
153 get
155 throw new NotImplementedException ();
157 // do a check for isModifiable when implementing this property
158 set
160 throw new NotImplementedException ();
163 #endregion
165 #region CustomStartCap [TODO]
166 [MonoTODO]
167 public CustomLineCap CustomStartCap
169 get
171 throw new NotImplementedException ();
174 // do a check for isModifiable when implementing this property
175 set
177 throw new NotImplementedException ();
180 #endregion
182 #region DashCap
183 [MonoTODO]
184 public DashCap DashCap {
185 get {
186 return _dashCap;
189 set {
190 EnsureModifiable();
191 _dashCap = value;
194 #endregion
196 #region DashOffset
197 public float DashOffset
200 get
202 return _dashOffset;
205 set
207 EnsureModifiable();
208 _dashOffset = value;
211 #endregion
213 #region DashPattern
215 public float [] DashPattern
217 get
219 return (float [])_dashPattern.Clone();
222 set
224 EnsureModifiable();
226 _dashPattern = value;
227 DashStyle = (_dashPattern == null) ? DashStyle.Solid : DashStyle.Custom;
230 #endregion
232 #region DashStyle
233 public DashStyle DashStyle
235 get
237 return _dashStyle;
240 set
242 EnsureModifiable();
243 _dashStyle = value;
246 #endregion
248 #region StartCap [TODO - now allways endcap]
249 [MonoTODO]
250 public LineCap StartCap {
251 get {
252 return _startCap;
255 set {
256 EnsureModifiable();
257 _startCap = value;
260 #endregion
262 #region EndCap
263 [MonoTODO]
264 public LineCap EndCap
266 get
268 return _endCap;
271 set
273 EnsureModifiable();
275 _endCap = value;
278 #endregion
280 #region LineJoin [partial TODO - missed styles]
281 [MonoTODO]
282 public LineJoin LineJoin {
283 get {
284 return _lineJoin;
287 set {
288 EnsureModifiable();
289 _lineJoin = value;
293 #endregion
295 #region MiterLimit
296 public float MiterLimit
299 get
301 return _miterLimit;
304 set
306 EnsureModifiable();
308 _miterLimit = value;
312 #endregion
314 #region PenType
315 public PenType PenType
317 get
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;
327 else
328 return PenType.SolidColor;
331 #endregion
333 #region Transform
334 public Matrix Transform
336 get
338 return _transform.Clone();
341 set
343 EnsureModifiable();
345 value.CopyTo(_transform);
348 #endregion
350 #region Width
351 public float Width
353 get
355 return _width;
357 set
359 EnsureModifiable();
361 _width = value;
364 #endregion
366 #region Clone
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();
374 return clone;
376 #endregion
378 #region Dispose
379 public void Dispose ()
381 Dispose (true);
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
389 #endregion
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 ()
404 _transform.Reset ();
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);
434 #endregion
436 public void SetLineCap (LineCap startCap, LineCap endCap, DashCap dashCap)
438 StartCap = startCap;
439 DashCap = dashCap;
440 EndCap = endCap;
443 void EnsureModifiable() {
444 if (!isModifiable)
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 {
467 get {
468 if (!_transform.IsIdentity)
469 return false;
471 //FIXME: add more logic when more features will
472 // be implemented.
473 return true;
477 internal awt.Stroke GetNativeObject(geom.AffineTransform outputTransform, PenFit penFit) {
478 return GetNativeObject(null, outputTransform, penFit);
480 /// <summary>
481 ///
482 /// </summary>
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;
489 switch (DashStyle) {
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;
497 else {
498 if ((i & 1) == 0) {
499 // remove the size of caps from the opaque parts
500 dashPattern[i] = (_dashPattern[i] * Width) - Width;
501 if (_dashPattern[i] < 0)
502 dashPattern[i] = 0;
504 else
505 // add the size of caps to the transparent parts
506 dashPattern[i] = (_dashPattern[i] * Width) + Width;
510 break;
511 case DashStyle.Dash:
512 dashPattern = DASH_ARRAY;
513 break;
514 case DashStyle.DashDot:
515 dashPattern = DASHDOT_ARRAY;
516 break;
517 case DashStyle.DashDotDot:
518 dashPattern = DASHDOTDOT_ARRAY;
519 break;
521 // default:
522 // case DashStyle.Solid:
523 // break;
526 int join;
527 switch (LineJoin) {
528 case LineJoin.Bevel:
529 join = java.awt.BasicStroke.JOIN_BEVEL;
530 break;
531 default:
532 case LineJoin.Miter:
533 case LineJoin.MiterClipped:
534 join = java.awt.BasicStroke.JOIN_MITER;
535 break;
536 case LineJoin.Round:
537 join = java.awt.BasicStroke.JOIN_ROUND;
538 break;
541 // We go by End cap for now.
542 int cap;
543 switch (EndCap) {
544 default:
545 case LineCap.Square:
546 case LineCap.SquareAnchor:
547 cap = awt.BasicStroke.CAP_SQUARE;
548 break;
549 case LineCap.Round:
550 case LineCap.RoundAnchor:
551 cap = awt.BasicStroke.CAP_ROUND;
552 break;
553 case LineCap.Flat:
554 cap = awt.BasicStroke.CAP_BUTT;
555 break;
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);
575 #endregion