1 //
2 // Mono.Cairo.Context.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 //   Alp Toker (alp@atoker.com)
9 //
10 // (C) Ximian Inc, 2003.
11 // (C) Novell Inc, 2003.
12 //
13 // This is an OO wrapper API for the Cairo API.
14 //
15 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
16 //
17 // Permission is hereby granted, free of charge, to any person obtaining
18 // a copy of this software and associated documentation files (the
19 // "Software"), to deal in the Software without restriction, including
20 // without limitation the rights to use, copy, modify, merge, publish,
21 // distribute, sublicense, and/or sell copies of the Software, and to
22 // permit persons to whom the Software is furnished to do so, subject to
23 // the following conditions:
24 //
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
27 //
28 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 //
36 
37 using System;
38 using System.Runtime.InteropServices;
39 using Cairo;
40 
41 namespace Cairo {
42 
43         public struct Point
44         {
PointCairo.Point45 		public Point (int x, int y)
46 		{
47 			this.x = x;
48 			this.y = y;
49 		}
50 
51 		int x, y;
52 		public int X {
53 			get { return x; }
54 			set { x = value; }
55 		}
56 
57 		public int Y {
58 			get { return y; }
59 			set { y = value; }
60 		}
61 	}
62 
63         public struct PointD
64         {
PointDCairo.PointD65 		public PointD (double x, double y)
66 		{
67 			this.x = x;
68 			this.y = y;
69 		}
70 
71 		double x, y;
72 		public double X {
73 			get { return x; }
74 			set { x = value; }
75 		}
76 
77 		public double Y {
78 			get { return y; }
79 			set { y = value; }
80 		}
81 	}
82 
83 
84         public struct Distance
85         {
DistanceCairo.Distance86 		public Distance (double dx, double dy)
87 		{
88 			this.dx = dx;
89 			this.dy = dy;
90 		}
91 
92 		double dx, dy;
93 		public double Dx {
94 			get { return dx; }
95 			set { dx = value; }
96 		}
97 
98 		public double Dy {
99 			get { return dy; }
100 			set { dy = value; }
101 		}
102 	}
103 
104         public struct Color
105         {
ColorCairo.Color106 		public Color(double r, double g, double b) : this (r, g, b, 1.0)
107 		{
108 		}
109 
ColorCairo.Color110 		public Color(double r, double g, double b, double a)
111 		{
112 			this.r = r;
113 			this.g = g;
114 			this.b = b;
115 			this.a = a;
116 		}
117 
118 		double r, g, b, a;
119 
120 		public double R {
121 			get { return r; }
122 			set { r = value; }
123 		}
124 
125 		public double G {
126 			get { return g; }
127 			set { g = value; }
128 		}
129 
130 		public double B {
131 			get { return b; }
132 			set { b = value; }
133 		}
134 
135 		public double A {
136 			get { return a; }
137 			set { a = value; }
138 		}
139 
140 	}
141 
142 	[Obsolete ("Renamed Cairo.Context per suggestion from cairo binding guidelines.")]
143 	public class Graphics : Context {
Graphics(IntPtr state)144 		public Graphics (IntPtr state) : base (state) {}
Graphics(Surface surface)145 		public Graphics (Surface surface) : base (surface) {}
146 	}
147 
148         public class Context : IDisposable
149         {
150                 internal IntPtr state = IntPtr.Zero;
151 
152 		static int native_glyph_size, c_compiler_long_size;
153 
Context()154 		static Context ()
155 		{
156 			//
157 			// This is used to determine what kind of structure
158 			// we should use to marshal Glyphs, as the public
159 			// definition in Cairo uses `long', which can be
160 			// 32 bits or 64 bits depending on the platform.
161 			//
162 			// We assume that sizeof(long) == sizeof(void*)
163 			// except in the case of Win64 where sizeof(long)
164 			// is 32 bits
165 			//
166 			int ptr_size = IntPtr.Size;
167 
168 			PlatformID platform = Environment.OSVersion.Platform;
169 			if (platform == PlatformID.Win32NT ||
170 			    platform == PlatformID.Win32S ||
171 			    platform == PlatformID.Win32Windows ||
172 			    platform == PlatformID.WinCE ||
173 			    ptr_size == 4){
174 				c_compiler_long_size = 4;
175 				native_glyph_size = Marshal.SizeOf (typeof (NativeGlyph_4byte_longs));
176 			} else {
177 				c_compiler_long_size = 8;
178 				native_glyph_size = Marshal.SizeOf (typeof (Glyph));
179 			}
180 		}
181 
Context(Surface surface)182                 public Context (Surface surface)
183                 {
184 			state = NativeMethods.cairo_create (surface.Handle);
185                 }
186 
Context(IntPtr state)187 		public Context (IntPtr state)
188 		{
189 			this.state = state;
190 		}
191 
~Context()192 		~Context ()
193 		{
194 			Dispose (false);
195 		}
196 
IDisposable.Dispose()197 		void IDisposable.Dispose ()
198 		{
199 			Dispose (true);
200 			GC.SuppressFinalize (this);
201 		}
202 
Dispose(bool disposing)203                 protected virtual void Dispose (bool disposing)
204                 {
205 			if (!disposing){
206 				Console.Error.WriteLine ("Cairo.Context: called from finalization thread, programmer is missing a call to Dispose");
207 				return;
208 			}
209 
210 			if (state == IntPtr.Zero)
211 				return;
212 
213 			//Console.WriteLine ("Destroying");
214                         NativeMethods.cairo_destroy (state);
215 			state = IntPtr.Zero;
216                 }
217 
Save()218                 public void Save ()
219                 {
220                         NativeMethods.cairo_save (state);
221                 }
222 
Restore()223                 public void Restore ()
224                 {
225                         NativeMethods.cairo_restore (state);
226                 }
227 
228 		public Antialias Antialias {
229 			get { return NativeMethods.cairo_get_antialias (state); }
230 			set { NativeMethods.cairo_set_antialias (state, value); }
231 		}
232 
233                 public Cairo.Status Status {
234                         get {
235                                 return NativeMethods.cairo_status (state);
236                         }
237                 }
238 
239                 public IntPtr Handle {
240                         get {
241                                 return state;
242                         }
243                 }
244 
245                 public Cairo.Operator Operator {
246                         set {
247                                 NativeMethods.cairo_set_operator (state, value);
248                         }
249 
250                         get {
251                                 return NativeMethods.cairo_get_operator (state);
252                         }
253                 }
254 
255 		[Obsolete("Use SetSourceColor")]
256                 public Cairo.Color Color {
257 			set {
258 				NativeMethods.cairo_set_source_rgba (state, value.R, value.G, value.B, value.A);
259 			}
260                 }
261 
262 		[Obsolete ("Use Color property")]
263                 public Cairo.Color ColorRgb {
264 			set {
265 				Color = new Color (value.R, value.G, value.B);
266 			}
267                 }
268 
269                 public double Tolerance {
270 			get {
271 				return NativeMethods.cairo_get_tolerance (state);
272 			}
273 
274                         set {
275                                 NativeMethods.cairo_set_tolerance (state, value);
276                         }
277                 }
278 
279                 public Cairo.FillRule FillRule {
280                         set {
281                                 NativeMethods.cairo_set_fill_rule (state, value);
282                         }
283 
284                         get {
285                                 return NativeMethods.cairo_get_fill_rule (state);
286                         }
287                 }
288 
289                 public double LineWidth {
290                         set {
291                                 NativeMethods.cairo_set_line_width (state, value);
292                         }
293 
294                         get {
295                                 return NativeMethods.cairo_get_line_width (state);
296                         }
297                 }
298 
299                 public Cairo.LineCap LineCap {
300                         set {
301                                 NativeMethods.cairo_set_line_cap (state, value);
302                         }
303 
304                         get {
305                                 return NativeMethods.cairo_get_line_cap (state);
306                         }
307                 }
308 
309                 public Cairo.LineJoin LineJoin {
310                         set {
311                                 NativeMethods.cairo_set_line_join (state, value);
312                         }
313 
314                         get {
315                                 return NativeMethods.cairo_get_line_join (state);
316                         }
317                 }
318 
SetDash(double [] dashes, double offset)319                 public void SetDash (double [] dashes, double offset)
320                 {
321                         NativeMethods.cairo_set_dash (state, dashes, dashes.Length, offset);
322                 }
323 
324                 public Pattern Pattern {
325                         set {
326                                 NativeMethods.cairo_set_source (state, value.Pointer);
327                         }
328 
329 			get {
330 				return new Pattern (NativeMethods.cairo_get_source (state));
331 			}
332                 }
333 
334                 public Pattern Source {
335                         set {
336                                 NativeMethods.cairo_set_source (state, value.Pointer);
337                         }
338 
339 			get {
340 				return Pattern.Lookup (NativeMethods.cairo_get_source (state));
341 			}
342                 }
343 
344                 public double MiterLimit {
345                         set {
346                                 NativeMethods.cairo_set_miter_limit (state, value);
347                         }
348 
349                         get {
350                                 return NativeMethods.cairo_get_miter_limit (state);
351                         }
352                 }
353 
354                 public PointD CurrentPoint {
355                         get {
356                                 double x, y;
357                                 NativeMethods.cairo_get_current_point (state, out x, out y);
358                                 return new PointD (x, y);
359                         }
360                 }
361 
362                 public Cairo.Surface Target {
363                         set {
364 				if (state != IntPtr.Zero)
365 					NativeMethods.cairo_destroy (state);
366 
367 				state = NativeMethods.cairo_create (value.Handle);
368                         }
369 
370                         get {
371                                 return Cairo.Surface.LookupExternalSurface (
372                                         NativeMethods.cairo_get_target (state));
373                         }
374                 }
375 
376 		public Cairo.ScaledFont ScaledFont {
377                         set {
378 				NativeMethods.cairo_set_scaled_font (state, value.Handle);
379                         }
380 
381                         get {
382                                 return new ScaledFont (NativeMethods.cairo_get_scaled_font (state));
383                         }
384                 }
385 
386 		public uint ReferenceCount {
387 			get { return NativeMethods.cairo_get_reference_count (state); }
388 		}
389 
SetSourceColor(Color color)390 		public void SetSourceColor (Color color)
391 		{
392 			NativeMethods.cairo_set_source_rgba (state, color.R, color.G, color.B, color.A);
393 		}
394 
SetSourceRGB(double r, double g, double b)395 		public void SetSourceRGB (double r, double g, double b)
396 		{
397 			NativeMethods.cairo_set_source_rgb (state, r, g, b);
398 		}
399 
SetSourceRGBA(double r, double g, double b, double a)400 		public void SetSourceRGBA (double r, double g, double b, double a)
401 		{
402 			NativeMethods.cairo_set_source_rgba (state, r, g, b, a);
403 		}
404 
405 		//[Obsolete ("Use SetSource method (with double parameters)")]
SetSourceSurface(Surface source, int x, int y)406 		public void SetSourceSurface (Surface source, int x, int y)
407 		{
408 			NativeMethods.cairo_set_source_surface (state, source.Handle, x, y);
409 		}
410 
SetSource(Surface source, double x, double y)411 		public void SetSource (Surface source, double x, double y)
412 		{
413 			NativeMethods.cairo_set_source_surface (state, source.Handle, x, y);
414 		}
415 
SetSource(Surface source)416 		public void SetSource (Surface source)
417 		{
418 			NativeMethods.cairo_set_source_surface (state, source.Handle, 0, 0);
419 		}
420 
421 #region Path methods
422 
NewPath()423                 public void NewPath ()
424                 {
425                         NativeMethods.cairo_new_path (state);
426                 }
427 
NewSubPath()428 		public void NewSubPath ()
429 		{
430 			NativeMethods.cairo_new_sub_path (state);
431 		}
432 
MoveTo(PointD p)433                 public void MoveTo (PointD p)
434                 {
435 			MoveTo (p.X, p.Y);
436                 }
437 
MoveTo(double x, double y)438 		public void MoveTo (double x, double y)
439 		{
440                         NativeMethods.cairo_move_to (state, x, y);
441 		}
442 
LineTo(PointD p)443                 public void LineTo (PointD p)
444 		{
445 			LineTo (p.X, p.Y);
446 		}
447 
LineTo(double x, double y)448 		public void LineTo (double x, double y)
449                 {
450                         NativeMethods.cairo_line_to (state, x, y);
451                 }
452 
CurveTo(PointD p1, PointD p2, PointD p3)453                 public void CurveTo (PointD p1, PointD p2, PointD p3)
454 		{
455 			CurveTo (p1.X, p1.Y, p2.X, p2.Y, p3.X, p3.Y);
456 		}
457 
CurveTo(double x1, double y1, double x2, double y2, double x3, double y3)458                 public void CurveTo (double x1, double y1, double x2, double y2, double x3, double y3)
459                 {
460                         NativeMethods.cairo_curve_to (state, x1, y1, x2, y2, x3, y3);
461                 }
462 
RelMoveTo(Distance d)463                 public void RelMoveTo (Distance d)
464 		{
465 			RelMoveTo (d.Dx, d.Dy);
466 		}
467 
RelMoveTo(double dx, double dy)468                 public void RelMoveTo (double dx, double dy)
469                 {
470                         NativeMethods.cairo_rel_move_to (state, dx, dy);
471                 }
472 
RelLineTo(Distance d)473                 public void RelLineTo (Distance d)
474                 {
475 			RelLineTo (d.Dx, d.Dy);
476                 }
477 
RelLineTo(double dx, double dy)478                 public void RelLineTo (double dx, double dy)
479 		{
480                         NativeMethods.cairo_rel_line_to (state, dx, dy);
481 		}
482 
RelCurveTo(Distance d1, Distance d2, Distance d3)483                 public void RelCurveTo (Distance d1, Distance d2, Distance d3)
484 		{
485 			RelCurveTo (d1.Dx, d1.Dy, d2.Dx, d2.Dy, d3.Dx, d3.Dy);
486 		}
487 
RelCurveTo(double dx1, double dy1, double dx2, double dy2, double dx3, double dy3)488                 public void RelCurveTo (double dx1, double dy1, double dx2, double dy2, double dx3, double dy3)
489                 {
490                         NativeMethods.cairo_rel_curve_to (state, dx1, dy1, dx2, dy2, dx3, dy3);
491                 }
492 
Arc(double xc, double yc, double radius, double angle1, double angle2)493                 public void Arc (double xc, double yc, double radius, double angle1, double angle2)
494                 {
495                         NativeMethods.cairo_arc (state, xc, yc, radius, angle1, angle2);
496                 }
497 
ArcNegative(double xc, double yc, double radius, double angle1, double angle2)498                 public void ArcNegative (double xc, double yc, double radius, double angle1, double angle2)
499                 {
500                         NativeMethods.cairo_arc_negative (state, xc, yc, radius, angle1, angle2);
501                 }
502 
Rectangle(Rectangle rectangle)503                 public void Rectangle (Rectangle rectangle)
504 		{
505 			Rectangle (rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
506 		}
507 
Rectangle(PointD p, double width, double height)508                 public void Rectangle (PointD p, double width, double height)
509 		{
510 			Rectangle (p.X, p.Y, width, height);
511 		}
512 
Rectangle(double x, double y, double width, double height)513                 public void Rectangle (double x, double y, double width, double height)
514                 {
515                         NativeMethods.cairo_rectangle (state, x, y, width, height);
516                 }
517 
ClosePath()518                 public void ClosePath ()
519                 {
520                         NativeMethods.cairo_close_path (state);
521                 }
522 
CopyPath()523 	        public Path CopyPath ()
524 		{
525 			return new Path (NativeMethods.cairo_copy_path (state));
526 		}
527 
CopyPathFlat()528 		public Path CopyPathFlat ()
529 		{
530 			return new Path (NativeMethods.cairo_copy_path_flat (state));
531 		}
532 
AppendPath(Path path)533 		public void AppendPath (Path path)
534 		{
535 			NativeMethods.cairo_append_path (state, path.handle);
536 		}
537 
538 #endregion
539 
540 #region Painting Methods
Paint()541 		public void Paint ()
542 		{
543 			NativeMethods.cairo_paint (state);
544 		}
545 
PaintWithAlpha(double alpha)546 		public void PaintWithAlpha (double alpha)
547 		{
548 			NativeMethods.cairo_paint_with_alpha (state, alpha);
549 		}
550 
Mask(Pattern pattern)551 		public void Mask (Pattern pattern)
552 		{
553 			NativeMethods.cairo_mask (state, pattern.Pointer);
554 		}
555 
MaskSurface(Surface surface, double surface_x, double surface_y)556 		public void MaskSurface (Surface surface, double surface_x, double surface_y)
557 		{
558 			NativeMethods.cairo_mask_surface (state, surface.Handle, surface_x, surface_y);
559 		}
560 
Stroke()561                 public void Stroke ()
562                 {
563                         NativeMethods.cairo_stroke (state);
564                 }
565 
StrokePreserve()566                 public void StrokePreserve ()
567                 {
568                         NativeMethods.cairo_stroke_preserve (state);
569                 }
570 
StrokeExtents()571 		public Rectangle StrokeExtents ()
572 		{
573 			double x1, y1, x2, y2;
574 			NativeMethods.cairo_stroke_extents (state, out x1, out y1, out x2, out y2);
575 			return new Rectangle (x1, y1, x2, y2);
576 		}
577 
Fill()578                 public void Fill ()
579                 {
580                         NativeMethods.cairo_fill (state);
581                 }
582 
FillExtents()583                 public Rectangle FillExtents ()
584 		{
585 			double x1, y1, x2, y2;
586 			NativeMethods.cairo_fill_extents (state, out x1, out y1, out x2, out y2);
587 			return new Rectangle (x1, y1, x2, y2);
588 		}
589 
FillPreserve()590 		public void FillPreserve ()
591 		{
592 			NativeMethods.cairo_fill_preserve (state);
593 		}
594 
595 #endregion
596 
Clip()597                 public void Clip ()
598                 {
599                         NativeMethods.cairo_clip (state);
600                 }
601 
ClipPreserve()602 		public void ClipPreserve ()
603 		{
604 			NativeMethods.cairo_clip_preserve (state);
605 		}
606 
ResetClip()607 		public void ResetClip ()
608 		{
609 			NativeMethods.cairo_reset_clip (state);
610 		}
611 
InStroke(double x, double y)612 		public bool InStroke (double x, double y)
613 		{
614 			return NativeMethods.cairo_in_stroke (state, x, y);
615 		}
616 
InFill(double x, double y)617 		public bool InFill (double x, double y)
618 		{
619 			return NativeMethods.cairo_in_fill (state, x, y);
620 		}
621 
PopGroup()622 		public Pattern PopGroup ()
623 		{
624 			return Pattern.Lookup (NativeMethods.cairo_pop_group (state));
625 		}
626 
PopGroupToSource()627 		public void PopGroupToSource ()
628 		{
629 			NativeMethods.cairo_pop_group_to_source (state);
630 		}
631 
PushGroup()632 		public void PushGroup ()
633 		{
634 			NativeMethods.cairo_push_group (state);
635 		}
636 
PushGroup(Content content)637 		public void PushGroup (Content content)
638 		{
639 			NativeMethods.cairo_push_group_with_content (state, content);
640 		}
641 
642 		public Surface GroupTarget {
643 			get {
644 				IntPtr surface = NativeMethods.cairo_get_group_target (state);
645 				return Surface.LookupSurface (surface);
646 			}
647 		}
648 
Rotate(double angle)649                 public void Rotate (double angle)
650                 {
651                         NativeMethods.cairo_rotate (state, angle);
652                 }
653 
Scale(double sx, double sy)654                 public void Scale (double sx, double sy)
655                 {
656                         NativeMethods.cairo_scale (state, sx, sy);
657                 }
658 
Translate(double tx, double ty)659                 public void Translate (double tx, double ty)
660                 {
661                         NativeMethods.cairo_translate (state, tx, ty);
662                 }
663 
Transform(Matrix m)664 		public void Transform (Matrix m)
665 		{
666 			NativeMethods.cairo_transform (state, m);
667 		}
668 
669 #region Methods that will become obsolete in the long term, after 1.2.5 becomes wildly available
670 
671 		//[Obsolete("Use UserToDevice instead")]
TransformPoint(ref double x, ref double y)672 		public void TransformPoint (ref double x, ref double y)
673 		{
674                 	NativeMethods.cairo_user_to_device (state, ref x, ref y);
675 		}
676 
677 		//[Obsolete("Use UserToDeviceDistance instead")]
TransformDistance(ref double dx, ref double dy)678                 public void TransformDistance (ref double dx, ref double dy)
679 		{
680 			NativeMethods.cairo_user_to_device_distance (state, ref dx, ref dy);
681 		}
682 
683 		//[Obsolete("Use InverseTransformPoint instead")]
InverseTransformPoint(ref double x, ref double y)684 		public void InverseTransformPoint (ref double x, ref double y)
685 		{
686 			NativeMethods.cairo_device_to_user (state, ref x, ref y);
687 		}
688 
689 		//[Obsolete("Use DeviceToUserDistance instead")]
InverseTransformDistance(ref double dx, ref double dy)690 		public void InverseTransformDistance (ref double dx, ref double dy)
691 		{
692 			NativeMethods.cairo_device_to_user_distance (state, ref dx, ref dy);
693 		}
694 #endregion
695 
UserToDevice(ref double x, ref double y)696 		public void UserToDevice (ref double x, ref double y)
697 		{
698                 	NativeMethods.cairo_user_to_device (state, ref x, ref y);
699 		}
700 
UserToDeviceDistance(ref double dx, ref double dy)701                 public void UserToDeviceDistance (ref double dx, ref double dy)
702 		{
703 			NativeMethods.cairo_user_to_device_distance (state, ref dx, ref dy);
704 		}
705 
DeviceToUser(ref double x, ref double y)706 		public void DeviceToUser (ref double x, ref double y)
707 		{
708 			NativeMethods.cairo_device_to_user (state, ref x, ref y);
709 		}
710 
DeviceToUserDistance(ref double dx, ref double dy)711 		public void DeviceToUserDistance (ref double dx, ref double dy)
712 		{
713 			NativeMethods.cairo_device_to_user_distance (state, ref dx, ref dy);
714 		}
715 
716                 public Cairo.Matrix Matrix {
717                         set {
718                                 NativeMethods.cairo_set_matrix (state, value);
719                         }
720 
721                         get {
722 				Matrix m = new Matrix();
723 				NativeMethods.cairo_get_matrix (state, m);
724                                 return m;
725                         }
726                 }
727 
SetFontSize(double scale)728 		public void SetFontSize (double scale)
729 		{
730 			NativeMethods.cairo_set_font_size (state, scale);
731 		}
732 
IdentityMatrix()733 		public void IdentityMatrix ()
734 		{
735 			NativeMethods.cairo_identity_matrix (state);
736 		}
737 
738 		[Obsolete ("Use SetFontSize() instead.")]
FontSetSize(double scale)739 		public void FontSetSize (double scale)
740 		{
741 			SetFontSize (scale);
742 		}
743 
744 		[Obsolete ("Use SetFontSize() instead.")]
745 		public double FontSize {
746 			set { SetFontSize (value); }
747 		}
748 
749 		public Matrix FontMatrix {
750 			get {
751 				Matrix m;
752 				NativeMethods.cairo_get_font_matrix (state, out m);
753 				return m;
754 			}
755 			set { NativeMethods.cairo_set_font_matrix (state, value); }
756 		}
757 
758 		public FontOptions FontOptions {
759 			get {
760 				FontOptions options = new FontOptions ();
761 				NativeMethods.cairo_get_font_options (state, options.Handle);
762 				return options;
763 			}
764 			set { NativeMethods.cairo_set_font_options (state, value.Handle); }
765 		}
766 
767 		[StructLayout(LayoutKind.Sequential)]
768 		internal struct NativeGlyph_4byte_longs {
769 			public int index;
770 			public double x;
771 			public double y;
772 
NativeGlyph_4byte_longsCairo.Context.NativeGlyph_4byte_longs773 			public NativeGlyph_4byte_longs (Glyph source)
774 			{
775 				index = (int) source.index;
776 				x = source.x;
777 				y = source.y;
778 			}
779 		}
780 
FromGlyphToUnManagedMemory(Glyph [] glyphs)781 		static internal IntPtr FromGlyphToUnManagedMemory(Glyph [] glyphs)
782 		{
783 			IntPtr dest = Marshal.AllocHGlobal (native_glyph_size * glyphs.Length);
784 			long pos = dest.ToInt64();
785 
786 			if (c_compiler_long_size == 8){
787 				foreach (Glyph g in glyphs){
788 					Marshal.StructureToPtr (g, (IntPtr)pos, false);
789 					pos += native_glyph_size;
790 				}
791 			} else {
792 				foreach (Glyph g in glyphs){
793 					NativeGlyph_4byte_longs n = new NativeGlyph_4byte_longs (g);
794 
795 					Marshal.StructureToPtr (n, (IntPtr)pos, false);
796 					pos += native_glyph_size;
797 				}
798 			}
799 
800 			return dest;
801 		}
802 
ShowGlyphs(Glyph[] glyphs)803                 public void ShowGlyphs (Glyph[] glyphs)
804 		{
805                         IntPtr ptr;
806 
807                         ptr = FromGlyphToUnManagedMemory (glyphs);
808 
809                         NativeMethods.cairo_show_glyphs (state, ptr, glyphs.Length);
810 
811                         Marshal.FreeHGlobal (ptr);
812 		}
813 
814 		[Obsolete("The matrix argument was never used, use ShowGlyphs(Glyphs []) instead")]
ShowGlyphs(Matrix matrix, Glyph[] glyphs)815                 public void ShowGlyphs (Matrix matrix, Glyph[] glyphs)
816                 {
817 			ShowGlyphs (glyphs);
818                 }
819 
820 		[Obsolete("The matrix argument was never used, use GlyphPath(Glyphs []) instead")]
GlyphPath(Matrix matrix, Glyph[] glyphs)821                 public void GlyphPath (Matrix matrix, Glyph[] glyphs)
822                 {
823 			GlyphPath (glyphs);
824 		}
825 
GlyphPath(Glyph[] glyphs)826 		public void GlyphPath (Glyph[] glyphs)
827 		{
828                         IntPtr ptr;
829 
830                         ptr = FromGlyphToUnManagedMemory (glyphs);
831 
832                         NativeMethods.cairo_glyph_path (state, ptr, glyphs.Length);
833 
834                         Marshal.FreeHGlobal (ptr);
835 
836                 }
837 
838                 public FontExtents FontExtents {
839                         get {
840                                 FontExtents f_extents;
841                                 NativeMethods.cairo_font_extents (state, out f_extents);
842                                 return f_extents;
843                         }
844                 }
845 
CopyPage()846 		public void CopyPage ()
847 		{
848 			NativeMethods.cairo_copy_page (state);
849 		}
850 
851 		[Obsolete ("Use SelectFontFace() instead.")]
FontFace(string family, FontSlant slant, FontWeight weight)852 		public void FontFace (string family, FontSlant slant, FontWeight weight)
853 		{
854 			SelectFontFace (family, slant, weight);
855 		}
856 
857 		public FontFace ContextFontFace {
858 			get {
859 				return Cairo.FontFace.Lookup (NativeMethods.cairo_get_font_face (state));
860 			}
861 
862 			set {
863 				NativeMethods.cairo_set_font_face (state, value == null ? IntPtr.Zero : value.Handle);
864 			}
865 		}
866 
SelectFontFace(string family, FontSlant slant, FontWeight weight)867 		public void SelectFontFace (string family, FontSlant slant, FontWeight weight)
868 		{
869 			NativeMethods.cairo_select_font_face (state, family, slant, weight);
870 		}
871 
ShowPage()872 		public void ShowPage ()
873 		{
874 			NativeMethods.cairo_show_page (state);
875 		}
876 
ShowText(string str)877                 public void ShowText (string str)
878                 {
879                         NativeMethods.cairo_show_text (state, str);
880                 }
881 
TextPath(string str)882                 public void TextPath (string str)
883                 {
884                         NativeMethods.cairo_text_path  (state, str);
885                 }
886 
TextExtents(string utf8)887 		public TextExtents TextExtents (string utf8)
888 		{
889 			TextExtents extents;
890 			NativeMethods.cairo_text_extents (state, utf8, out extents);
891 			return extents;
892 		}
893 
GlyphExtents(Glyph[] glyphs)894 		public TextExtents GlyphExtents (Glyph[] glyphs)
895 		{
896 			IntPtr ptr = FromGlyphToUnManagedMemory (glyphs);
897 
898 			TextExtents extents;
899 
900 			NativeMethods.cairo_glyph_extents (state, ptr, glyphs.Length, out extents);
901 
902 			Marshal.FreeHGlobal (ptr);
903 
904 			return extents;
905 		}
906         }
907 }
908