* attribute.cs (GetMarshal): Work even if "DefineCustom" is
[mono.git] / mcs / class / Mono.Cairo / Mono.Cairo / Graphics.cs
1 //
2 // Mono.Cairo.Graphics.cs
3 //
4 // Author:
5 //   Duncan Mak (duncan@ximian.com)
6 //   Miguel de Icaza (miguel@novell.com)
7 //   Hisham Mardam Bey (hisham.mardambey@gmail.com)
8 //
9 // (C) Ximian Inc, 2003.
10 // (C) Novell Inc, 2003.
11 //
12 // This is an OO wrapper API for the Cairo API.
13 //
14 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
15 //
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
23 // 
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
26 // 
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 //
35
36 using System;
37 using System.Runtime.InteropServices;
38 using Cairo;
39
40 namespace Cairo {
41
42         public class Point
43         {
44                 public int X;
45                 public int Y;
46                 
47                 public Point (int x, int y)
48                 {
49                         X = x;
50                         Y = y;
51                 }               
52         }
53            
54         public class PointD
55         {
56                 public double X;
57                 public double Y;
58                 
59                 public PointD (double x, double y)
60                 {
61                         X = x;
62                         Y = y;
63                 }
64         }
65    
66
67         public class Distance
68         {
69                 public double Dx;
70                 public double Dy;
71                 
72                 public Distance (double x, double y)
73                 {
74                         Dx = x;
75                         Dy = y;
76                 }               
77         }
78               
79         public class Color
80         {
81                 public double R;
82                 public double G;
83                 public double B;
84                 public double A;
85                 
86                 public Color(double r, double g, double b, double a)
87                 {
88                         R = r;
89                         G = g;
90                         B = b;
91                         A = a;
92                 }
93         }
94    
95         public class Graphics : IDisposable 
96         {
97                 internal IntPtr state = IntPtr.Zero;
98                 //private Surface surface;
99                 
100                 public Graphics (Surface surface)
101                 {
102                         state = CairoAPI.cairo_create (surface.Pointer);
103                 }
104                 
105                 public Graphics (IntPtr state)
106                 {
107                         this.state = state;
108                 }
109                 
110                 ~Graphics ()
111                 {
112                         Dispose (false);
113                 }
114
115                 void IDisposable.Dispose ()
116                 {
117                         Dispose (true);
118                         GC.SuppressFinalize (this);
119                 }
120                 
121                 protected virtual void Dispose (bool disposing)
122                 {
123                         if (!disposing){
124                                 //Console.WriteLine ("Cairo.Graphics: called from thread");
125                                 return;
126                         }
127                         
128                         if (state == IntPtr.Zero)
129                                 return;
130
131                         CairoAPI.cairo_destroy (state);
132                         state = IntPtr.Zero;
133                 }
134
135                 public Cairo.Graphics Copy ()
136                 {
137                         IntPtr dest;
138                         CairoAPI.cairo_copy (out dest, state);
139                         return new Cairo.Graphics (dest);
140                 }
141                 
142                 public void Save ()
143                 {
144                         CairoAPI.cairo_save (state);
145                 }
146
147                 public void Restore ()
148                 {
149                         CairoAPI.cairo_restore (state);
150                 }
151
152                 public Antialias Antialias {
153                         get { return CairoAPI.cairo_get_antialias (state); }
154                         set { CairoAPI.cairo_set_antialias (state, value); }
155                 }
156                 
157                 public Cairo.Status Status {
158                         get {
159                                 return CairoAPI.cairo_status (state);
160                         }
161                 }
162                 
163                 /*
164                 public string StatusString {
165                  get {
166                                 return CairoAPI.cairo_status_to_string (state);
167                         }
168                  }
169                  */ 
170                 public IntPtr Handle {
171                         get {
172                                 return state;
173                         }
174                 }
175                 
176                 public Cairo.Operator Operator {
177                         set {
178                                 CairoAPI.cairo_set_operator (state, value);
179                         }
180
181                         get {
182                                 return CairoAPI.cairo_get_operator (state);
183                         }
184                 }
185                 
186                 public Cairo.Color Color {
187                         set { 
188                                 CairoAPI.cairo_set_source_rgba (state, value.R, 
189                                                           value.G, value.B,
190                                                           value.A);
191                         }                       
192                 }
193                 
194                 public Cairo.Color ColorRgb {
195                         set { 
196                                 CairoAPI.cairo_set_source_rgb (state, value.R, 
197                                                            value.G, value.B);
198                         }
199                 }               
200
201                 public double Tolerance {
202                         set {
203                                 CairoAPI.cairo_set_tolerance (state, value);
204                         }
205                 }
206                 
207                 public Cairo.FillRule FillRule {
208                         set {
209                                 CairoAPI.cairo_set_fill_rule (state, value);
210                         }
211
212                         get {
213                                 return CairoAPI.cairo_get_fill_rule (state);
214                         }
215                 }
216                                         
217                 public double LineWidth {
218                         set {
219                                 CairoAPI.cairo_set_line_width (state, value);
220                         }
221
222                         get {
223                                 return CairoAPI.cairo_get_line_width (state);
224                         }
225                 }
226
227                 public Cairo.LineCap LineCap {
228                         set {
229                                 CairoAPI.cairo_set_line_cap (state, value);
230                         }
231
232                         get {
233                                 return CairoAPI.cairo_current_line_cap (state);
234                         }
235                 }
236
237                 public Cairo.LineJoin LineJoin {
238                         set {
239                                 CairoAPI.cairo_set_line_join (state, value);
240                         }
241
242                         get {
243                                 return CairoAPI.cairo_get_line_join (state);
244                         }
245                 }
246
247                 public void SetDash (double [] dashes, int ndash, double offset)
248                 {
249                         CairoAPI.cairo_set_dash (state, dashes, ndash, offset);
250                 }
251                 
252                 public Pattern Pattern {
253                         set {
254                                 CairoAPI.cairo_set_source (state, value.Pointer);
255                         }
256                         
257                         get {
258                                 return new Pattern (CairoAPI.cairo_get_source (state));
259                         }
260                 }               
261                 
262                 public Pattern Source {
263                         set {
264                                 CairoAPI.cairo_set_source (state, value.Pointer);
265                         }
266                         
267                         get {
268                                 return new Pattern (CairoAPI.cairo_get_source (state));
269                         }
270                 }
271
272                 public double MiterLimit {
273                         set {
274                                 CairoAPI.cairo_set_miter_limit (state, value);
275                         }
276
277                         get {
278                                 return CairoAPI.cairo_get_miter_limit (state);
279                         }
280                 }
281
282                 public PointD CurrentPoint {
283                         get {
284                                 double x, y;
285                                 CairoAPI.cairo_get_current_point (state, out x, out y);
286                                 return new PointD (x, y);
287                         }
288                 }
289
290                 public Cairo.Surface TargetSurface {
291                         set {
292                                 state = CairoAPI.cairo_create (value.Pointer);                          
293                                 //CairoAPI.cairo_set_target_surface (state, value.Handle);
294                         }
295
296                         get {
297                                 return Cairo.Surface.LookupExternalSurface (
298                                         CairoAPI.cairo_get_target (state));
299                         }
300                 }
301
302 #region Path methods
303                 
304                 public void NewPath ()
305                 {
306                         CairoAPI.cairo_new_path (state);
307                 }
308         
309                 public void CurrentPath (MoveToCallback move_to, 
310                                          LineToCallback line_to,
311                                          CurveToCallback curve_to,
312                                          ClosePathCallback close_path,
313                                          object closure)
314                 {
315                         
316                 }
317                 
318                 public void MoveTo (PointD p)
319                 {
320                                                 MoveTo (p.X, p.Y);
321                 }
322
323                                 public void MoveTo (double x, double y)
324                                 {
325                         CairoAPI.cairo_move_to (state, x, y);
326                                 }
327                 
328                 public void LineTo (PointD p)
329                                 {
330                                                 LineTo (p.X, p.Y);
331                                 }
332
333                                 public void LineTo (double x, double y)
334                 {
335                         CairoAPI.cairo_line_to (state, x, y);
336                 }
337
338                 public void CurveTo (PointD p1, PointD p2, PointD p3)
339                                 {
340                                                 CurveTo (p1.X, p1.Y, p2.X, p2.Y, p3.X, p3.Y);
341                                 }
342                                 
343                 public void CurveTo (double x1, double y1, double x2, double y2, double x3, double y3)
344                 {
345                         CairoAPI.cairo_curve_to (state, x1, y1, x2, y2, x3, y3);
346                 }
347
348                 public void RelMoveTo (PointD p)
349                                 {
350                                                 RelMoveTo (p.X, p.Y);
351                                 }
352                                 
353                 public void RelMoveTo (double x, double y)
354                 {
355                         CairoAPI.cairo_rel_move_to (state, x, y);
356                 }
357
358                 public void RelLineTo (PointD p)
359                 {
360                                                 RelLineTo (p.X, p.Y);
361                 }
362
363                 public void RelLineTo (double x, double y)
364                                 {
365                         CairoAPI.cairo_rel_line_to (state, x, y);
366                                 }
367
368                 public void RelCurveTo (double dx1, double dy1, double dx2, double dy2, double dx3, double dy3)
369                 {
370                         CairoAPI.cairo_rel_curve_to (state, dx1, dy1, dx2, dy2, dx3, dy3); 
371                 }
372
373                 public void Arc (double xc, double yc, double radius, double angel1, double angel2)
374                 {
375                         CairoAPI.cairo_arc (state, xc, yc, radius, angel1, angel2);
376                 }
377
378                 public void ArcNegative (double xc, double yc, double radius, double angel1, double angel2)
379                 {
380                         CairoAPI.cairo_arc_negative (state, xc, yc, radius, angel1, angel2);
381                 }
382                 
383                 public void ArcTo (PointD p1, PointD p2, double radius)
384                 {
385                                 ArcTo (p1.X, p1.Y, p2.X, p2.Y, radius);
386                 }
387                 
388                 public void ArcTo (double x1, double y1, double x2, double y2, double radius)
389                 {
390                         CairoAPI.cairo_arc_to (state, x1, y1, x2, y2, radius);
391                 }
392                 
393                 public void Rectangle (PointD p, double width, double height)
394                                 {
395                                                 Rectangle (p.X, p.Y, width, height);
396                                 }
397
398                 public void Rectangle (double x, double y, double width, double height)
399                 {
400                         CairoAPI.cairo_rectangle (state, x, y, width, height);
401                 }
402                 
403                 public void ClosePath ()
404                 {
405                         CairoAPI.cairo_close_path (state);
406                 }
407 #endregion
408
409 #region Painting Methods
410
411                 public void Stroke ()
412                 {
413                         CairoAPI.cairo_stroke (state);
414                 }
415                 
416                 public void StrokePreserve ()
417                 {
418                         CairoAPI.cairo_stroke_preserve (state);
419                 }               
420
421                 public void Fill ()
422                 {
423                         CairoAPI.cairo_fill (state);
424                 }
425                 
426                 public void FillPreserve ()
427                 {
428                         CairoAPI.cairo_fill_preserve (state);
429                 }
430
431 #endregion
432
433                 public void Clip ()
434                 {
435                         CairoAPI.cairo_clip (state);
436                 }
437
438                 public void ClipReset ()
439                 {
440                         CairoAPI.cairo_reset_clip (state);
441                 }
442                 
443                 public bool InStroke (double x, double y)
444                 {
445                         return CairoAPI.cairo_in_stroke (state, x, y);
446                 }
447
448                 public bool InFill (double x, double y)
449                 {
450                         return CairoAPI.cairo_in_fill (state, x, y);
451                 }
452
453
454 #region Modified state
455
456                 public void SetTargetImage (
457                         string data, Cairo.Format format, int width, int height, int stride)
458                 {
459                         CairoAPI.cairo_image_surface_create_for_data (data, format, width, height, stride);
460                 }
461
462                 public void SetTargetDrawable (IntPtr dpy, IntPtr drawable, IntPtr visual, int width, int height)
463                 {
464                         CairoAPI.cairo_xlib_surface_create (dpy, drawable, visual, width, height);
465                 }               
466 #endregion
467
468                 public void Rotate (double angle)
469                 {
470                         CairoAPI.cairo_rotate (state, angle);
471                 }
472
473                 public void Scale (double sx, double sy)
474                 {
475                         CairoAPI.cairo_scale (state, sx, sy);
476                 }
477
478                 public void Translate (double tx, double ty)
479                 {
480                         CairoAPI.cairo_translate (state, tx, ty);
481                 }
482
483                 public PointD TransformPoint
484                 {
485                         get {
486                                 double x; double y;                             
487                                 CairoAPI.cairo_user_to_device (state, out x, out y);
488                                 return new PointD(x, y);
489                         }
490                 }
491                 
492                 public Distance TransformDistance 
493                 {
494                         get {
495                                 double dx; double dy;
496                                 CairoAPI.cairo_user_to_device_distance (state, out dx, out dy);
497                                 return new Distance(dx, dy);
498                         }
499                 }
500
501                 public PointD InverseTransformPoint
502                 {
503                         get {
504                                 double x; double y;
505                                 CairoAPI.cairo_device_to_user (state, out x, out y);
506                                 return new PointD (x, y);
507                         }
508                 }
509
510                 public Distance InverseTransformDistance
511                 {
512                         get {
513                                 double dx; double dy;
514                                 CairoAPI.cairo_device_to_user_distance (state, out dx, out dy);
515                                 return new Distance (dx, dy);
516                         }
517                 }
518                 
519                 public Cairo.Matrix Matrix {
520                         set {
521                                 CairoAPI.cairo_set_matrix (state, value.Pointer);
522                         }
523
524                         get {
525                                 Matrix_T m = new Matrix_T ();
526                                 CairoAPI.cairo_get_matrix (state, m);
527                                 return new Matrix (m);
528                         }
529                 }
530                 /*
531                 public Font Font {
532                         set {
533                                 CairoAPI.cairo_set_font (state, value.Pointer);
534
535                         }
536
537                         get {
538                                 IntPtr fnt = IntPtr.Zero;
539
540                                 fnt = CairoAPI.cairo_current_font (state);
541
542                                 return new Font (fnt);
543                         }
544                 }
545                  */ 
546
547                 public void FontSetSize (double size)
548                 {
549                         CairoAPI.cairo_set_font_size (state, size);
550                 }
551                 
552                 public void FontSetMatrix (Matrix m)
553                 {
554                         CairoAPI.cairo_set_font_matrix (state, m.Pointer);
555                 }
556                 
557                 /*
558                 public void TransformFont (Matrix matrix)
559                 {
560                         CairoAPI.cairo_transform_font (state, matrix.Pointer);
561                 }
562                  */ 
563
564                 
565                 static internal IntPtr FromGlyphToUnManagedMemory(Glyph [] glyphs)
566                 {
567                         int size =  Marshal.SizeOf (glyphs[0]);
568                         IntPtr dest = Marshal.AllocHGlobal (size * glyphs.Length);
569                         int pos = dest.ToInt32();
570
571                         for (int i=0; i < glyphs.Length; i++, pos += size)
572                                 Marshal.StructureToPtr (glyphs[i], (IntPtr)pos, false);
573
574                         return dest;
575                 }
576
577
578                 public void ShowGlyphs (Matrix matrix, Glyph[] glyphs)
579                 {
580
581                         IntPtr ptr;
582
583                         ptr = FromGlyphToUnManagedMemory (glyphs);
584                         
585                         CairoAPI.cairo_show_glyphs (state, ptr, glyphs.Length);
586
587                         Marshal.FreeHGlobal (ptr);              
588                      
589                 }
590
591                 public void GlyphPath (Matrix matrix, Glyph[] glyphs)
592                 {
593
594                         IntPtr ptr;
595
596                         ptr = FromGlyphToUnManagedMemory (glyphs);
597
598                         CairoAPI.cairo_glyph_path (state, ptr, glyphs.Length);
599
600                         Marshal.FreeHGlobal (ptr);
601
602                 }
603
604                 public FontExtents FontExtents {
605                         get {
606                                 
607                                 FontExtents f_extents = new FontExtents();
608                                 CairoAPI.cairo_font_extents (state, ref f_extents);
609                                 return f_extents;
610                         }
611                 }
612                 
613                 public void FontFace (string family, FontSlant s, FontWeight w)
614                 {
615                         CairoAPI.cairo_select_font_face (state, family, s, w);
616                 }
617                 
618                 public double FontSize {
619                         set { CairoAPI.cairo_set_font_size (state, value); }
620                 }
621                 
622                 public void ShowText (string str)
623                 {
624                         CairoAPI.cairo_show_text (state, str);
625                 }               
626                 
627                 public void TextPath (string str)
628                 {
629                         CairoAPI.cairo_text_path  (state, str);
630                 }               
631         }
632 }