removed exec attribute
[mono.git] / mcs / class / System.Drawing / System.Drawing / Pen.jvm.cs
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
12 //
13
14 using System;
15 using System.Drawing.Drawing2D;
16 using System.Runtime.InteropServices;
17
18 using awt = java.awt;
19 using geom = java.awt.geom;
20
21 namespace System.Drawing \r
22 {
23
24         public sealed class Pen : MarshalByRefObject, ICloneable, IDisposable, awt.Stroke\r
25         {
26                 #region Member Vars
27
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};
32
33                 internal bool isModifiable = true;
34
35                 Brush _brush;
36                 DashStyle _dashStyle;
37                 DashCap _dashCap;
38                 LineCap _startCap;
39                 LineCap _endCap;
40
41                 LineJoin _lineJoin;
42
43                 PenAlignment _alignment;
44                 Matrix _transform;
45                 float _width;
46                 float _dashOffset;
47                 float[] _dashPattern;
48                 //float[] _compoundArray;
49
50                 float _miterLimit;
51
52                 #endregion
53
54                 #region Ctors. and Dtor
55
56                 public Pen (Brush brush) : this (brush, 1.0F)
57                 {}
58
59                 public Pen (Color color) : this (color, 1.0F)
60                 {}
61
62                 public Pen (Color color, float width) : this(new SolidBrush(color), width)
63                 {}
64
65                 public Pen (Brush brush, float width)
66                 {
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();
77                 }
78                 #endregion
79                 //
80                 // Properties
81                 //
82                 #region Alignment [TODO]
83                 public PenAlignment Alignment \r
84                 {
85                         get \r
86                         {
87                                 return _alignment;
88                         }
89
90                         set \r
91                         {
92                                 EnsureModifiable();
93                                 _alignment = value;
94                         }
95                 }
96                 #endregion
97
98                 #region Brush
99                 public Brush Brush \r
100                 {
101                         get \r
102                         {
103                                 return _brush;
104                         }
105
106                         set \r
107                         {
108                                 EnsureModifiable();
109                                 if (value == null)
110                                         throw new ArgumentNullException("brush");
111                                 _brush = value;
112                         }
113                 }
114                 #endregion
115
116                 #region Color
117                 public Color Color \r
118                 {
119                         get \r
120                         {
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;
127                         }
128
129                         set \r
130                         {
131                                 EnsureModifiable();
132                                 _brush = new SolidBrush (value);
133                         }
134                 }
135                 #endregion 
136
137                 #region CompoundArray [TODO]
138                 [MonoTODO]
139                 public float[] CompoundArray {
140                         get {
141                                 throw new NotImplementedException ();
142                         }
143                         set {
144                                 throw new NotImplementedException ();
145                         }
146                 }
147                 #endregion
148             
149                 #region CustomEndCap [TODO]
150                 [MonoTODO]
151                 public CustomLineCap CustomEndCap \r
152                 {
153                         get \r
154                         {
155                                 throw new NotImplementedException ();
156                         }
157                         // do a check for isModifiable when implementing this property
158                         set \r
159                         {
160                                 throw new NotImplementedException ();                                
161                         }
162                 }
163                 #endregion 
164
165                 #region CustomStartCap [TODO]
166                 [MonoTODO]
167                 public CustomLineCap CustomStartCap \r
168                 {
169                         get \r
170                         {
171                                 throw new NotImplementedException ();                                
172                         }
173
174                         // do a check for isModifiable when implementing this property
175                         set \r
176                         {
177                                 throw new NotImplementedException ();                                
178                         }
179                 }
180                 #endregion
181
182                 #region DashCap
183                 [MonoTODO]
184                 public DashCap DashCap {
185                         get {
186                                 return _dashCap;
187                         }
188
189                         set {
190                                 EnsureModifiable();
191                                 _dashCap = value;
192                         }
193                 }
194                 #endregion
195
196                 #region DashOffset
197                 public float DashOffset \r
198                 {
199
200                         get \r
201                         {
202                                 return _dashOffset;
203                         }
204
205                         set \r
206                         {
207                                 EnsureModifiable();
208                                 _dashOffset = value;
209                         }
210                 }
211                 #endregion
212
213                 #region DashPattern
214
215                 public float [] DashPattern \r
216                 {
217                         get \r
218                         {
219                                 return (float [])_dashPattern.Clone();
220                         }
221
222                         set \r
223                         {
224                                 EnsureModifiable();
225
226                                 _dashPattern = value;
227                                 DashStyle = (_dashPattern == null) ? DashStyle.Solid : DashStyle.Custom;
228                         }
229                 }
230                 #endregion
231
232                 #region DashStyle
233                 public DashStyle DashStyle \r
234                 {
235                         get \r
236                         {
237                                 return _dashStyle;
238                         }
239
240                         set \r
241                         {
242                                 EnsureModifiable();
243                                 _dashStyle = value;
244                         }
245                 }
246                 #endregion 
247
248                 #region StartCap [TODO - now allways endcap]
249                 [MonoTODO]
250                 public LineCap StartCap {
251                         get { 
252                                 return _startCap;
253                         }
254
255                         set {
256                                 EnsureModifiable();
257                                 _startCap = value;
258                         }
259                 }
260                 #endregion
261
262                 #region EndCap 
263                 [MonoTODO]
264                 public LineCap EndCap \r
265                 {
266                         get \r
267                         {
268                                 return _endCap;
269                         }
270
271                         set \r
272                         {
273                                 EnsureModifiable();
274
275                                 _endCap = value;
276                         }
277                 }
278                 #endregion
279  
280                 #region LineJoin [partial TODO - missed styles]
281                 [MonoTODO]
282                 public LineJoin LineJoin {
283                         get {
284                                 return _lineJoin;
285                         }
286
287                         set {
288                                 EnsureModifiable();
289                                 _lineJoin = value;
290                         }
291                 }
292
293                 #endregion
294
295                 #region MiterLimit 
296                 public float MiterLimit \r
297                 {
298
299                         get \r
300                         {
301                                 return _miterLimit;
302                         }
303
304                         set \r
305                         {
306                                 EnsureModifiable();
307
308                                 _miterLimit = value;                    
309                         }
310                             
311                 }
312                 #endregion
313
314                 #region PenType
315                 public PenType PenType \r
316                 {
317                         get \r
318                         {
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;
329                         }
330                 }
331                 #endregion
332
333                 #region Transform
334                 public Matrix Transform \r
335                 {
336                         get \r
337                         {
338                                 return _transform.Clone();
339                         }
340                                         
341                         set \r
342                         {
343                                 EnsureModifiable();
344
345                                 value.CopyTo(_transform);
346                         }
347                 }
348                 #endregion
349
350                 #region Width
351                 public float Width \r
352                 {
353                         get \r
354                         {
355                                 return _width;
356                         }
357                         set \r
358                         {
359                                 EnsureModifiable();
360                                                                                                 
361                                 _width = value;
362                         }
363                 }
364                 #endregion
365
366                 #region Clone
367                 public object Clone ()
368                 {
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;
375                 }
376                 #endregion
377
378                 #region Dispose 
379                 public void Dispose ()
380                 {
381                         Dispose (true);
382                 }
383                 void Dispose (bool disposing)
384                 {
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
388                 }
389                 #endregion
390
391                 #region Transform Funcs
392                 public void MultiplyTransform (Matrix matrix)
393                 {
394                         _transform.Multiply (matrix);
395                 }
396
397                 public void MultiplyTransform (Matrix matrix, MatrixOrder order)
398                 {
399                         _transform.Multiply (matrix, order);
400                 }
401
402                 public void ResetTransform ()
403                 {
404                         _transform.Reset ();
405                 }
406
407                 public void RotateTransform (float angle)
408                 {
409                         _transform.Rotate (angle);
410                 }
411
412                 public void RotateTransform (float angle, MatrixOrder order)
413                 {
414                         _transform.Rotate (angle, order);
415                 }
416
417                 public void ScaleTransform (float sx, float sy)
418                 {
419                         _transform.Scale (sx, sy);
420                 }
421
422                 public void ScaleTransform (float sx, float sy, MatrixOrder order)
423                 {
424                         _transform.Scale (sx, sy, order);
425                 }
426
427                 public void TranslateTransform (float dx, float dy) {
428                         _transform.Translate (dx, dy);
429                 }
430
431                 public void TranslateTransform (float dx, float dy, MatrixOrder order) {
432                         _transform.Translate (dx, dy, order);
433                 }
434                 #endregion
435
436                 public void SetLineCap (LineCap startCap, LineCap endCap, DashCap dashCap)
437                 {
438                         StartCap = startCap;
439                         DashCap = dashCap;
440                         EndCap = endCap;
441                 }
442
443                 void EnsureModifiable() {
444                         if (!isModifiable)
445                                 throw new ArgumentException ("You may not change this Pen because it does not belong to you.");
446                 }
447
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
454
455                         double K = coordsTransform.getScaleX(); // m00
456                         double L = coordsTransform.getShearY(); // m10
457                         double M = coordsTransform.getShearX(); // m01
458                         double N = coordsTransform.getScaleY(); // m11
459
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));
463                 }
464
465                 
466                 internal bool CanCreateBasicStroke {
467                         get {
468                                 if (!_transform.IsIdentity)
469                                         return false;
470
471                                 //FIXME: add more logic when more features will
472                                 // be implemented.
473                                 return true;
474                         }
475                 }
476
477                 internal awt.Stroke GetNativeObject(geom.AffineTransform outputTransform, PenFit penFit) {
478                         return GetNativeObject(null, outputTransform, penFit);
479                 }
480                 /// <summary>\r
481                 /// \r
482                 /// </summary>\r
483                 /// <param name="outputTransform">transform which will be applied on the final shape</param>\r
484                 /// <param name="fitPen">ensure the shape will wide enough to be visible</param>\r
485                 /// <returns></returns>
486                 internal awt.Stroke GetNativeObject(geom.AffineTransform penTransform, geom.AffineTransform outputTransform, PenFit penFit) {
487                         float[] dashPattern = null;\r
488 \r
489                         switch (DashStyle) {\r
490                                 case DashStyle.Custom:\r
491                                         if (_dashPattern != null) {\r
492                                                 dashPattern = new float[_dashPattern.Length];\r
493                                                 for(int i = 0; i < _dashPattern.Length; i++) {
494
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;
503                                                                 }
504                                                                 else
505                                                                         // add the size of caps to the transparent parts
506                                                                         dashPattern[i] = (_dashPattern[i] * Width) + Width;
507                                                         }
508                                                 }\r
509                                         }\r
510                                         break;\r
511                                 case DashStyle.Dash:\r
512                                         dashPattern = DASH_ARRAY;\r
513                                         break;\r
514                                 case DashStyle.DashDot:\r
515                                         dashPattern = DASHDOT_ARRAY;\r
516                                         break;\r
517                                 case DashStyle.DashDotDot:\r
518                                         dashPattern = DASHDOTDOT_ARRAY;\r
519                                         break;\r
520                                 \r
521                                         //                              default:\r
522                                         //                              case DashStyle.Solid:\r
523                                         //                                      break;\r
524                         }\r
525 \r
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;\r
538                                         break;\r
539                         }\r
540 \r
541                         // We go by End cap for now.\r
542                         int cap;\r
543                         switch (EndCap) {\r
544                                 default:\r
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;\r
556                         }\r
557 \r
558                         geom.AffineTransform penT = _transform.NativeObject;\r
559                         if (penTransform != null && !penTransform.isIdentity()) {\r
560                                 penT = (geom.AffineTransform)penT.clone();\r
561                                 penT.concatenate(penTransform);\r
562                         }\r
563 \r
564                         return StrokeFactory.CreateStroke(Width, cap, \r
565                                 join, MiterLimit, dashPattern, DashOffset,\r
566                                 penT, outputTransform, penFit);
567                 }
568
569                 #region Stroke Members\r
570 \r
571                 awt.Shape awt.Stroke.createStrokedShape(awt.Shape arg_0) {\r
572                         return GetNativeObject(null, PenFit.NotThin).createStrokedShape(arg_0);\r
573                 }\r
574 \r
575                 #endregion
576         }
577 }