2 // Mono.Cairo.Context.cs
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)
10 // (C) Ximian Inc, 2003.
11 // (C) Novell Inc, 2003.
13 // This is an OO wrapper API for the Cairo API.
15 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
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:
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
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.
38 using System.Runtime.InteropServices;
44 [Obsolete ("Renamed Cairo.Context per suggestion from cairo binding guidelines.")]
45 public class Graphics : Context {
46 public Graphics (IntPtr state) : base (state) {}
47 public Graphics (Surface surface) : base (surface) {}
50 public class Context : IDisposable
52 IntPtr handle = IntPtr.Zero;
54 static int native_glyph_size, c_compiler_long_size;
59 // This is used to determine what kind of structure
60 // we should use to marshal Glyphs, as the public
61 // definition in Cairo uses `long', which can be
62 // 32 bits or 64 bits depending on the platform.
64 // We assume that sizeof(long) == sizeof(void*)
65 // except in the case of Win64 where sizeof(long)
68 int ptr_size = Marshal.SizeOf (typeof (IntPtr));
70 PlatformID platform = Environment.OSVersion.Platform;
71 if (platform == PlatformID.Win32NT ||
72 platform == PlatformID.Win32S ||
73 platform == PlatformID.Win32Windows ||
74 platform == PlatformID.WinCE ||
76 c_compiler_long_size = 4;
77 native_glyph_size = Marshal.SizeOf (typeof (NativeGlyph_4byte_longs));
79 c_compiler_long_size = 8;
80 native_glyph_size = Marshal.SizeOf (typeof (Glyph));
84 public Context (Surface surface) : this (NativeMethods.cairo_create (surface.Handle), true)
89 public Context (IntPtr handle, bool owner)
93 NativeMethods.cairo_reference (handle);
94 if (CairoDebug.Enabled)
95 CairoDebug.OnAllocated (handle);
99 public Context (IntPtr state) : this (state, true)
108 public void Dispose ()
111 GC.SuppressFinalize (this);
114 protected virtual void Dispose (bool disposing)
116 if (!disposing || CairoDebug.Enabled)
117 CairoDebug.OnDisposed<Context> (handle, disposing);
119 if (!disposing|| handle == IntPtr.Zero)
122 NativeMethods.cairo_destroy (handle);
123 handle = IntPtr.Zero;
129 NativeMethods.cairo_save (handle);
132 public void Restore ()
134 NativeMethods.cairo_restore (handle);
137 public Antialias Antialias {
138 get { return NativeMethods.cairo_get_antialias (handle); }
139 set { NativeMethods.cairo_set_antialias (handle, value); }
142 public Cairo.Status Status {
144 return NativeMethods.cairo_status (handle);
148 public IntPtr Handle {
154 public Operator Operator {
156 NativeMethods.cairo_set_operator (handle, value);
160 return NativeMethods.cairo_get_operator (handle);
164 [Obsolete ("Use SetSourceColor method")]
167 SetSourceColor (value);
171 [Obsolete ("Use SetSourceRGBA method")]
172 public Cairo.Color ColorRgb {
174 Color = new Color (value.R, value.G, value.B);
178 public double Tolerance {
180 return NativeMethods.cairo_get_tolerance (handle);
184 NativeMethods.cairo_set_tolerance (handle, value);
188 public Cairo.FillRule FillRule {
190 NativeMethods.cairo_set_fill_rule (handle, value);
194 return NativeMethods.cairo_get_fill_rule (handle);
198 public double LineWidth {
200 NativeMethods.cairo_set_line_width (handle, value);
204 return NativeMethods.cairo_get_line_width (handle);
208 public Cairo.LineCap LineCap {
210 NativeMethods.cairo_set_line_cap (handle, value);
214 return NativeMethods.cairo_get_line_cap (handle);
218 public Cairo.LineJoin LineJoin {
220 NativeMethods.cairo_set_line_join (handle, value);
224 return NativeMethods.cairo_get_line_join (handle);
228 public void SetDash (double [] dashes, double offset)
230 NativeMethods.cairo_set_dash (handle, dashes, dashes.Length, offset);
233 [Obsolete("Use GetSource/GetSource")]
234 public Pattern Pattern {
243 //This is obsolete because it wasn't obvious it needed to be disposed
244 [Obsolete("Use GetSource/GetSource")]
245 public Pattern Source {
254 public void SetSource (Pattern source)
256 NativeMethods.cairo_set_source (handle, source.Handle);
259 public Pattern GetSource ()
261 var ptr = NativeMethods.cairo_get_source (handle);
262 return Cairo.Pattern.Lookup (ptr, false);
265 public double MiterLimit {
267 NativeMethods.cairo_set_miter_limit (handle, value);
271 return NativeMethods.cairo_get_miter_limit (handle);
275 public PointD CurrentPoint {
278 NativeMethods.cairo_get_current_point (handle, out x, out y);
279 return new PointD (x, y);
283 public bool HasCurrentPoint {
285 return NativeMethods.cairo_has_current_point (handle);
289 [Obsolete ("Use GetTarget/SetTarget")]
290 public Cairo.Surface Target {
292 if (handle != IntPtr.Zero)
293 NativeMethods.cairo_destroy (handle);
295 handle = NativeMethods.cairo_create (value.Handle);
303 public Surface GetTarget ()
305 return Surface.Lookup (NativeMethods.cairo_get_target (handle), false);
308 public void SetTarget (Surface target)
310 if (handle != IntPtr.Zero)
311 NativeMethods.cairo_destroy (handle);
312 handle = NativeMethods.cairo_create (target.Handle);
315 [Obsolete("Use GetScaledFont/SetScaledFont")]
316 public ScaledFont ScaledFont {
318 SetScaledFont (value);
322 return GetScaledFont ();
326 public ScaledFont GetScaledFont ()
328 return new ScaledFont (NativeMethods.cairo_get_scaled_font (handle), false);
331 public void SetScaledFont (ScaledFont font)
333 NativeMethods.cairo_set_scaled_font (handle, font.Handle);
336 public uint ReferenceCount {
337 get { return NativeMethods.cairo_get_reference_count (handle); }
340 public void SetSourceColor (Color color)
342 NativeMethods.cairo_set_source_rgba (handle, color.R, color.G, color.B, color.A);
345 public void SetSourceRGB (double r, double g, double b)
347 NativeMethods.cairo_set_source_rgb (handle, r, g, b);
350 public void SetSourceRGBA (double r, double g, double b, double a)
352 NativeMethods.cairo_set_source_rgba (handle, r, g, b, a);
355 //[Obsolete ("Use SetSource method (with double parameters)")]
356 public void SetSourceSurface (Surface source, int x, int y)
358 NativeMethods.cairo_set_source_surface (handle, source.Handle, x, y);
361 public void SetSource (Surface source, double x, double y)
363 NativeMethods.cairo_set_source_surface (handle, source.Handle, x, y);
366 public void SetSource (Surface source)
368 NativeMethods.cairo_set_source_surface (handle, source.Handle, 0, 0);
373 public void NewPath ()
375 NativeMethods.cairo_new_path (handle);
378 public void NewSubPath ()
380 NativeMethods.cairo_new_sub_path (handle);
383 public void MoveTo (PointD p)
388 public void MoveTo (double x, double y)
390 NativeMethods.cairo_move_to (handle, x, y);
393 public void LineTo (PointD p)
398 public void LineTo (double x, double y)
400 NativeMethods.cairo_line_to (handle, x, y);
403 public void CurveTo (PointD p1, PointD p2, PointD p3)
405 CurveTo (p1.X, p1.Y, p2.X, p2.Y, p3.X, p3.Y);
408 public void CurveTo (double x1, double y1, double x2, double y2, double x3, double y3)
410 NativeMethods.cairo_curve_to (handle, x1, y1, x2, y2, x3, y3);
413 public void RelMoveTo (Distance d)
415 RelMoveTo (d.Dx, d.Dy);
418 public void RelMoveTo (double dx, double dy)
420 NativeMethods.cairo_rel_move_to (handle, dx, dy);
423 public void RelLineTo (Distance d)
425 RelLineTo (d.Dx, d.Dy);
428 public void RelLineTo (double dx, double dy)
430 NativeMethods.cairo_rel_line_to (handle, dx, dy);
433 public void RelCurveTo (Distance d1, Distance d2, Distance d3)
435 RelCurveTo (d1.Dx, d1.Dy, d2.Dx, d2.Dy, d3.Dx, d3.Dy);
438 public void RelCurveTo (double dx1, double dy1, double dx2, double dy2, double dx3, double dy3)
440 NativeMethods.cairo_rel_curve_to (handle, dx1, dy1, dx2, dy2, dx3, dy3);
443 public void Arc (double xc, double yc, double radius, double angle1, double angle2)
445 NativeMethods.cairo_arc (handle, xc, yc, radius, angle1, angle2);
448 public void ArcNegative (double xc, double yc, double radius, double angle1, double angle2)
450 NativeMethods.cairo_arc_negative (handle, xc, yc, radius, angle1, angle2);
453 public void Rectangle (Rectangle rectangle)
455 Rectangle (rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
458 public void Rectangle (PointD p, double width, double height)
460 Rectangle (p.X, p.Y, width, height);
463 public void Rectangle (double x, double y, double width, double height)
465 NativeMethods.cairo_rectangle (handle, x, y, width, height);
468 public void ClosePath ()
470 NativeMethods.cairo_close_path (handle);
473 public Path CopyPath ()
475 return new Path (NativeMethods.cairo_copy_path (handle));
478 public Path CopyPathFlat ()
480 return new Path (NativeMethods.cairo_copy_path_flat (handle));
483 public void AppendPath (Path path)
485 NativeMethods.cairo_append_path (handle, path.Handle);
490 #region Painting Methods
493 NativeMethods.cairo_paint (handle);
496 public void PaintWithAlpha (double alpha)
498 NativeMethods.cairo_paint_with_alpha (handle, alpha);
501 public void Mask (Pattern pattern)
503 NativeMethods.cairo_mask (handle, pattern.Handle);
506 public void MaskSurface (Surface surface, double surface_x, double surface_y)
508 NativeMethods.cairo_mask_surface (handle, surface.Handle, surface_x, surface_y);
511 public void Stroke ()
513 NativeMethods.cairo_stroke (handle);
516 public void StrokePreserve ()
518 NativeMethods.cairo_stroke_preserve (handle);
521 public Rectangle StrokeExtents ()
523 double x1, y1, x2, y2;
524 NativeMethods.cairo_stroke_extents (handle, out x1, out y1, out x2, out y2);
525 return new Rectangle (x1, y1, x2 - x1, y2 - y1);
530 NativeMethods.cairo_fill (handle);
533 public Rectangle FillExtents ()
535 double x1, y1, x2, y2;
536 NativeMethods.cairo_fill_extents (handle, out x1, out y1, out x2, out y2);
537 return new Rectangle (x1, y1, x2 - x1, y2 - y1);
540 public void FillPreserve ()
542 NativeMethods.cairo_fill_preserve (handle);
549 NativeMethods.cairo_clip (handle);
552 public void ClipPreserve ()
554 NativeMethods.cairo_clip_preserve (handle);
557 public void ResetClip ()
559 NativeMethods.cairo_reset_clip (handle);
562 public bool InClip (double x, double y)
564 return NativeMethods.cairo_in_clip (handle, x, y);
567 public bool InStroke (double x, double y)
569 return NativeMethods.cairo_in_stroke (handle, x, y);
572 public bool InFill (double x, double y)
574 return NativeMethods.cairo_in_fill (handle, x, y);
577 public Pattern PopGroup ()
579 return Pattern.Lookup (NativeMethods.cairo_pop_group (handle), true);
582 public void PopGroupToSource ()
584 NativeMethods.cairo_pop_group_to_source (handle);
587 public void PushGroup ()
589 NativeMethods.cairo_push_group (handle);
592 public void PushGroup (Content content)
594 NativeMethods.cairo_push_group_with_content (handle, content);
597 [Obsolete ("Use GetGroupTarget()")]
598 public Surface GroupTarget {
600 return GetGroupTarget ();
604 public Surface GetGroupTarget ()
606 IntPtr surface = NativeMethods.cairo_get_group_target (handle);
607 return Surface.Lookup (surface, false);
610 public void Rotate (double angle)
612 NativeMethods.cairo_rotate (handle, angle);
615 public void Scale (double sx, double sy)
617 NativeMethods.cairo_scale (handle, sx, sy);
620 public void Translate (double tx, double ty)
622 NativeMethods.cairo_translate (handle, tx, ty);
625 public void Transform (Matrix m)
627 NativeMethods.cairo_transform (handle, m);
630 [Obsolete("Use UserToDevice instead")]
631 public void TransformPoint (ref double x, ref double y)
633 NativeMethods.cairo_user_to_device (handle, ref x, ref y);
636 [Obsolete("Use UserToDeviceDistance instead")]
637 public void TransformDistance (ref double dx, ref double dy)
639 NativeMethods.cairo_user_to_device_distance (handle, ref dx, ref dy);
642 [Obsolete("Use InverseTransformPoint instead")]
643 public void InverseTransformPoint (ref double x, ref double y)
645 NativeMethods.cairo_device_to_user (handle, ref x, ref y);
648 [Obsolete("Use DeviceToUserDistance instead")]
649 public void InverseTransformDistance (ref double dx, ref double dy)
651 NativeMethods.cairo_device_to_user_distance (handle, ref dx, ref dy);
654 public void UserToDevice (ref double x, ref double y)
656 NativeMethods.cairo_user_to_device (handle, ref x, ref y);
659 public void UserToDeviceDistance (ref double dx, ref double dy)
661 NativeMethods.cairo_user_to_device_distance (handle, ref dx, ref dy);
664 public void DeviceToUser (ref double x, ref double y)
666 NativeMethods.cairo_device_to_user (handle, ref x, ref y);
669 public void DeviceToUserDistance (ref double dx, ref double dy)
671 NativeMethods.cairo_device_to_user_distance (handle, ref dx, ref dy);
674 public Matrix Matrix {
676 NativeMethods.cairo_set_matrix (handle, value);
680 Matrix m = new Matrix();
681 NativeMethods.cairo_get_matrix (handle, m);
686 public void SetFontSize (double scale)
688 NativeMethods.cairo_set_font_size (handle, scale);
691 public void IdentityMatrix ()
693 NativeMethods.cairo_identity_matrix (handle);
696 [Obsolete ("Use SetFontSize() instead.")]
697 public void FontSetSize (double scale)
702 [Obsolete ("Use SetFontSize() instead.")]
703 public double FontSize {
704 set { SetFontSize (value); }
707 public Matrix FontMatrix {
710 NativeMethods.cairo_get_font_matrix (handle, out m);
713 set { NativeMethods.cairo_set_font_matrix (handle, value); }
716 public FontOptions FontOptions {
718 FontOptions options = new FontOptions ();
719 NativeMethods.cairo_get_font_options (handle, options.Handle);
722 set { NativeMethods.cairo_set_font_options (handle, value.Handle); }
725 [StructLayout(LayoutKind.Sequential)]
726 internal struct NativeGlyph_4byte_longs {
731 public NativeGlyph_4byte_longs (Glyph source)
733 index = (int) source.index;
739 static internal IntPtr FromGlyphToUnManagedMemory(Glyph [] glyphs)
741 IntPtr dest = Marshal.AllocHGlobal (native_glyph_size * glyphs.Length);
742 long pos = dest.ToInt64();
744 if (c_compiler_long_size == 8){
745 foreach (Glyph g in glyphs){
746 Marshal.StructureToPtr (g, (IntPtr)pos, false);
747 pos += native_glyph_size;
750 foreach (Glyph g in glyphs){
751 NativeGlyph_4byte_longs n = new NativeGlyph_4byte_longs (g);
753 Marshal.StructureToPtr (n, (IntPtr)pos, false);
754 pos += native_glyph_size;
761 public void ShowGlyphs (Glyph[] glyphs)
765 ptr = FromGlyphToUnManagedMemory (glyphs);
767 NativeMethods.cairo_show_glyphs (handle, ptr, glyphs.Length);
769 Marshal.FreeHGlobal (ptr);
772 [Obsolete("The matrix argument was never used, use ShowGlyphs(Glyphs []) instead")]
773 public void ShowGlyphs (Matrix matrix, Glyph[] glyphs)
778 [Obsolete("The matrix argument was never used, use GlyphPath(Glyphs []) instead")]
779 public void GlyphPath (Matrix matrix, Glyph[] glyphs)
784 public void GlyphPath (Glyph[] glyphs)
788 ptr = FromGlyphToUnManagedMemory (glyphs);
790 NativeMethods.cairo_glyph_path (handle, ptr, glyphs.Length);
792 Marshal.FreeHGlobal (ptr);
796 public FontExtents FontExtents {
798 FontExtents f_extents;
799 NativeMethods.cairo_font_extents (handle, out f_extents);
804 public void CopyPage ()
806 NativeMethods.cairo_copy_page (handle);
809 [Obsolete ("Use SelectFontFace() instead.")]
810 public void FontFace (string family, FontSlant slant, FontWeight weight)
812 SelectFontFace (family, slant, weight);
815 [Obsolete("Use GetFontFace/SetFontFace")]
816 public FontFace ContextFontFace {
818 return GetContextFontFace ();
821 SetContextFontFace (value);
825 public FontFace GetContextFontFace ()
827 return Cairo.FontFace.Lookup (NativeMethods.cairo_get_font_face (handle), false);
830 public void SetContextFontFace (FontFace value)
832 NativeMethods.cairo_set_font_face (handle, value == null ? IntPtr.Zero : value.Handle);
835 public void SelectFontFace (string family, FontSlant slant, FontWeight weight)
837 NativeMethods.cairo_select_font_face (handle, family, slant, weight);
840 public void ShowPage ()
842 NativeMethods.cairo_show_page (handle);
845 private static byte[] TerminateUtf8(byte[] utf8)
847 if (utf8.Length > 0 && utf8[utf8.Length - 1] == 0)
849 var termedArray = new byte[utf8.Length + 1];
850 Array.Copy(utf8, termedArray, utf8.Length);
851 termedArray[utf8.Length] = 0;
855 private static byte[] TerminateUtf8(string s)
857 // compute the byte count including the trailing \0
858 var byteCount = Encoding.UTF8.GetMaxByteCount(s.Length + 1);
859 var bytes = new byte[byteCount];
860 Encoding.UTF8.GetBytes(s, 0, s.Length, bytes, 0);
864 public void ShowText(string str)
866 NativeMethods.cairo_show_text (handle, TerminateUtf8(str));
869 public void ShowText(byte[] utf8)
871 NativeMethods.cairo_show_text (handle, TerminateUtf8(utf8));
874 public void TextPath(string str)
876 NativeMethods.cairo_text_path (handle, TerminateUtf8(str));
879 public void TextPath(byte[] utf8)
881 NativeMethods.cairo_text_path (handle, TerminateUtf8(utf8));
884 public TextExtents TextExtents(string s)
887 NativeMethods.cairo_text_extents (handle, TerminateUtf8(s), out extents);
891 public TextExtents TextExtents(byte[] utf8)
894 NativeMethods.cairo_text_extents (handle, TerminateUtf8(utf8), out extents);
898 public TextExtents GlyphExtents (Glyph[] glyphs)
900 IntPtr ptr = FromGlyphToUnManagedMemory (glyphs);
904 NativeMethods.cairo_glyph_extents (handle, ptr, glyphs.Length, out extents);
906 Marshal.FreeHGlobal (ptr);