From 70d1827058b692f2e3d1718c53597960a895f849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20G=2E=20Aragoneses?= Date: Tue, 5 Nov 2013 00:22:28 +0100 Subject: [PATCH] cairo: Throw ObjectDisposedException after an object has been disposed Potentially all these IDisposable classes could be used after being disposed, which would result in native crashes. We now do an explicit check and throw an exception in managed land when the object has been disposed. This is particularly useful because: a/ the native crashes are quite obscure, there no indication that you're using a disposed object b/ Gtk# is passing Context instances to user methods, and disposes them when the method returns. So if the user code keeps a reference to the Context, there a good chance it will try to use it after it's disposed. Other changes in this patch include: * Renaming a parameter to be more consistent with the other subsequent ctor called. * Replacing implementation of some [Obsolete()] methods with the call to the methods they were replaced with, to avoid redundancy and the need for more CheckDisposed() calls than necessary. * Throw ArgumentException when receiving an IntPtr.Zero as a handle, as a way to protect ourselves from wrapping invalid native pointers, and throwing ObjectDisposedExceptions because the object was invalid in the first place. Signed-off-by: Bertrand Lorentz --- cairo/Context.cs | 157 +++++++++++++++++++++++++++++++++++----- cairo/Device.cs | 23 +++++- cairo/FontFace.cs | 16 +++- cairo/FontOptions.cs | 56 +++++++++++--- cairo/Gradient.cs | 3 + cairo/ImageSurface.cs | 20 ++++- cairo/LinearGradient.cs | 1 + cairo/PSSurface.cs | 4 + cairo/Path.cs | 3 + cairo/Pattern.cs | 32 +++++++- cairo/PdfSurface.cs | 1 + cairo/Region.cs | 37 +++++++++- cairo/ScaledFont.cs | 19 ++++- cairo/SolidPattern.cs | 1 + cairo/Surface.cs | 37 ++++++++-- cairo/SurfacePattern.cs | 10 ++- cairo/SvgSurface.cs | 1 + cairo/XcbSurface.cs | 1 + cairo/XlibSurface.cs | 37 ++++++++-- 19 files changed, 404 insertions(+), 55 deletions(-) diff --git a/cairo/Context.cs b/cairo/Context.cs index 73df43807..fd3ea3c72 100644 --- a/cairo/Context.cs +++ b/cairo/Context.cs @@ -87,6 +87,9 @@ namespace Cairo { public Context (IntPtr handle, bool owner) { + if (handle == IntPtr.Zero) + throw new ArgumentException ("handle should not be NULL", "handle"); + this.handle = handle; if (!owner) NativeMethods.cairo_reference (handle); @@ -122,23 +125,38 @@ namespace Cairo { handle = IntPtr.Zero; } + void CheckDisposed () + { + if (handle == IntPtr.Zero) + throw new ObjectDisposedException ("Object has already been disposed"); + } + public void Save () { + CheckDisposed (); NativeMethods.cairo_save (handle); } public void Restore () { + CheckDisposed (); NativeMethods.cairo_restore (handle); } public Antialias Antialias { - get { return NativeMethods.cairo_get_antialias (handle); } - set { NativeMethods.cairo_set_antialias (handle, value); } + get { + CheckDisposed (); + return NativeMethods.cairo_get_antialias (handle); + } + set { + CheckDisposed (); + NativeMethods.cairo_set_antialias (handle, value); + } } public Cairo.Status Status { get { + CheckDisposed (); return NativeMethods.cairo_status (handle); } } @@ -151,10 +169,12 @@ namespace Cairo { public Operator Operator { set { + CheckDisposed (); NativeMethods.cairo_set_operator (handle, value); } get { + CheckDisposed (); return NativeMethods.cairo_get_operator (handle); } } @@ -162,69 +182,80 @@ namespace Cairo { [Obsolete ("Use SetSourceColor method")] public Color Color { set { - NativeMethods.cairo_set_source_rgba (handle, value.R, value.G, value.B, value.A); + SetSourceColor (value); } } [Obsolete ("Use SetSourceRGBA method")] public Cairo.Color ColorRgb { set { - Color = new Color (value.R, value.G, value.B); + SetSourceRGBA (value.R, value.G, value.B, value.A); } } public double Tolerance { get { + CheckDisposed (); return NativeMethods.cairo_get_tolerance (handle); } set { + CheckDisposed (); NativeMethods.cairo_set_tolerance (handle, value); } } public Cairo.FillRule FillRule { set { + CheckDisposed (); NativeMethods.cairo_set_fill_rule (handle, value); } get { + CheckDisposed (); return NativeMethods.cairo_get_fill_rule (handle); } } public double LineWidth { set { + CheckDisposed (); NativeMethods.cairo_set_line_width (handle, value); } get { + CheckDisposed (); return NativeMethods.cairo_get_line_width (handle); } } public Cairo.LineCap LineCap { set { + CheckDisposed (); NativeMethods.cairo_set_line_cap (handle, value); } get { + CheckDisposed (); return NativeMethods.cairo_get_line_cap (handle); } } public Cairo.LineJoin LineJoin { set { + CheckDisposed (); NativeMethods.cairo_set_line_join (handle, value); } get { + CheckDisposed (); return NativeMethods.cairo_get_line_join (handle); } } public void SetDash (double [] dashes, double offset) { + CheckDisposed (); NativeMethods.cairo_set_dash (handle, dashes, dashes.Length, offset); } @@ -251,27 +282,32 @@ namespace Cairo { public void SetSource (Pattern source) { + CheckDisposed (); NativeMethods.cairo_set_source (handle, source.Handle); } public Pattern GetSource () { + CheckDisposed (); var ptr = NativeMethods.cairo_get_source (handle); return Cairo.Pattern.Lookup (ptr, false); } public double MiterLimit { set { + CheckDisposed (); NativeMethods.cairo_set_miter_limit (handle, value); } get { + CheckDisposed (); return NativeMethods.cairo_get_miter_limit (handle); } } public PointD CurrentPoint { get { + CheckDisposed (); double x, y; NativeMethods.cairo_get_current_point (handle, out x, out y); return new PointD (x, y); @@ -281,10 +317,7 @@ namespace Cairo { [Obsolete ("Use GetTarget/SetTarget")] public Cairo.Surface Target { set { - if (handle != IntPtr.Zero) - NativeMethods.cairo_destroy (handle); - - handle = NativeMethods.cairo_create (value.Handle); + SetTarget (value); } get { @@ -294,11 +327,13 @@ namespace Cairo { public Surface GetTarget () { + CheckDisposed (); return Surface.Lookup (NativeMethods.cairo_get_target (handle), false); } public void SetTarget (Surface target) { + CheckDisposed (); if (handle != IntPtr.Zero) NativeMethods.cairo_destroy (handle); handle = NativeMethods.cairo_create (target.Handle); @@ -317,46 +352,57 @@ namespace Cairo { public ScaledFont GetScaledFont () { + CheckDisposed (); return new ScaledFont (NativeMethods.cairo_get_scaled_font (handle), false); } public void SetScaledFont (ScaledFont font) { + CheckDisposed (); NativeMethods.cairo_set_scaled_font (handle, font.Handle); } public uint ReferenceCount { - get { return NativeMethods.cairo_get_reference_count (handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_get_reference_count (handle); + } } public void SetSourceColor (Color color) { + CheckDisposed (); NativeMethods.cairo_set_source_rgba (handle, color.R, color.G, color.B, color.A); } public void SetSourceRGB (double r, double g, double b) { + CheckDisposed (); NativeMethods.cairo_set_source_rgb (handle, r, g, b); } public void SetSourceRGBA (double r, double g, double b, double a) { + CheckDisposed (); NativeMethods.cairo_set_source_rgba (handle, r, g, b, a); } //[Obsolete ("Use SetSource method (with double parameters)")] public void SetSourceSurface (Surface source, int x, int y) { + CheckDisposed (); NativeMethods.cairo_set_source_surface (handle, source.Handle, x, y); } public void SetSource (Surface source, double x, double y) { + CheckDisposed (); NativeMethods.cairo_set_source_surface (handle, source.Handle, x, y); } public void SetSource (Surface source) { + CheckDisposed (); NativeMethods.cairo_set_source_surface (handle, source.Handle, 0, 0); } @@ -364,11 +410,13 @@ namespace Cairo { public void NewPath () { + CheckDisposed (); NativeMethods.cairo_new_path (handle); } public void NewSubPath () { + CheckDisposed (); NativeMethods.cairo_new_sub_path (handle); } @@ -379,6 +427,7 @@ namespace Cairo { public void MoveTo (double x, double y) { + CheckDisposed (); NativeMethods.cairo_move_to (handle, x, y); } @@ -389,6 +438,7 @@ namespace Cairo { public void LineTo (double x, double y) { + CheckDisposed (); NativeMethods.cairo_line_to (handle, x, y); } @@ -399,6 +449,7 @@ namespace Cairo { public void CurveTo (double x1, double y1, double x2, double y2, double x3, double y3) { + CheckDisposed (); NativeMethods.cairo_curve_to (handle, x1, y1, x2, y2, x3, y3); } @@ -409,6 +460,7 @@ namespace Cairo { public void RelMoveTo (double dx, double dy) { + CheckDisposed (); NativeMethods.cairo_rel_move_to (handle, dx, dy); } @@ -419,6 +471,7 @@ namespace Cairo { public void RelLineTo (double dx, double dy) { + CheckDisposed (); NativeMethods.cairo_rel_line_to (handle, dx, dy); } @@ -429,16 +482,19 @@ namespace Cairo { public void RelCurveTo (double dx1, double dy1, double dx2, double dy2, double dx3, double dy3) { + CheckDisposed (); NativeMethods.cairo_rel_curve_to (handle, dx1, dy1, dx2, dy2, dx3, dy3); } public void Arc (double xc, double yc, double radius, double angle1, double angle2) { + CheckDisposed (); NativeMethods.cairo_arc (handle, xc, yc, radius, angle1, angle2); } public void ArcNegative (double xc, double yc, double radius, double angle1, double angle2) { + CheckDisposed (); NativeMethods.cairo_arc_negative (handle, xc, yc, radius, angle1, angle2); } @@ -454,31 +510,37 @@ namespace Cairo { public void Rectangle (double x, double y, double width, double height) { + CheckDisposed (); NativeMethods.cairo_rectangle (handle, x, y, width, height); } public void ClosePath () { + CheckDisposed (); NativeMethods.cairo_close_path (handle); } public Path CopyPath () { + CheckDisposed (); return new Path (NativeMethods.cairo_copy_path (handle)); } public Path CopyPathFlat () { + CheckDisposed (); return new Path (NativeMethods.cairo_copy_path_flat (handle)); } public void AppendPath (Path path) { + CheckDisposed (); NativeMethods.cairo_append_path (handle, path.Handle); } public void PathExtents (out double x1, out double y1, out double x2, out double y2) { + CheckDisposed (); NativeMethods.cairo_path_extents (handle, out x1, out y1, out x2, out y2); } @@ -487,36 +549,43 @@ namespace Cairo { #region Painting Methods public void Paint () { + CheckDisposed (); NativeMethods.cairo_paint (handle); } public void PaintWithAlpha (double alpha) { + CheckDisposed (); NativeMethods.cairo_paint_with_alpha (handle, alpha); } public void Mask (Pattern pattern) { + CheckDisposed (); NativeMethods.cairo_mask (handle, pattern.Handle); } public void MaskSurface (Surface surface, double surface_x, double surface_y) { + CheckDisposed (); NativeMethods.cairo_mask_surface (handle, surface.Handle, surface_x, surface_y); } public void Stroke () { + CheckDisposed (); NativeMethods.cairo_stroke (handle); } public void StrokePreserve () { + CheckDisposed (); NativeMethods.cairo_stroke_preserve (handle); } public Rectangle StrokeExtents () { + CheckDisposed (); double x1, y1, x2, y2; NativeMethods.cairo_stroke_extents (handle, out x1, out y1, out x2, out y2); return new Rectangle (x1, y1, x2 - x1, y2 - y1); @@ -524,11 +593,13 @@ namespace Cairo { public void Fill () { + CheckDisposed (); NativeMethods.cairo_fill (handle); } public Rectangle FillExtents () { + CheckDisposed (); double x1, y1, x2, y2; NativeMethods.cairo_fill_extents (handle, out x1, out y1, out x2, out y2); return new Rectangle (x1, y1, x2 - x1, y2 - y1); @@ -536,6 +607,7 @@ namespace Cairo { public void FillPreserve () { + CheckDisposed (); NativeMethods.cairo_fill_preserve (handle); } @@ -543,51 +615,61 @@ namespace Cairo { public void Clip () { + CheckDisposed (); NativeMethods.cairo_clip (handle); } public void ClipPreserve () { + CheckDisposed (); NativeMethods.cairo_clip_preserve (handle); } public void ResetClip () { + CheckDisposed (); NativeMethods.cairo_reset_clip (handle); } public bool InStroke (double x, double y) { + CheckDisposed (); return NativeMethods.cairo_in_stroke (handle, x, y); } public bool InClip (double x, double y) { + CheckDisposed (); return NativeMethods.cairo_in_clip (handle, x, y); } public bool InFill (double x, double y) { + CheckDisposed (); return NativeMethods.cairo_in_fill (handle, x, y); } public Pattern PopGroup () { + CheckDisposed (); return Pattern.Lookup (NativeMethods.cairo_pop_group (handle), true); } public void PopGroupToSource () { + CheckDisposed (); NativeMethods.cairo_pop_group_to_source (handle); } public void PushGroup () { + CheckDisposed (); NativeMethods.cairo_push_group (handle); } public void PushGroup (Content content) { + CheckDisposed (); NativeMethods.cairo_push_group_with_content (handle, content); } @@ -600,80 +682,91 @@ namespace Cairo { public Surface GetGroupTarget () { + CheckDisposed (); IntPtr surface = NativeMethods.cairo_get_group_target (handle); return Surface.Lookup (surface, false); } public void Rotate (double angle) { + CheckDisposed (); NativeMethods.cairo_rotate (handle, angle); } public void Scale (double sx, double sy) { + CheckDisposed (); NativeMethods.cairo_scale (handle, sx, sy); } public void Translate (double tx, double ty) { + CheckDisposed (); NativeMethods.cairo_translate (handle, tx, ty); } public void Transform (Matrix m) { + CheckDisposed (); NativeMethods.cairo_transform (handle, m); } [Obsolete("Use UserToDevice instead")] public void TransformPoint (ref double x, ref double y) { - NativeMethods.cairo_user_to_device (handle, ref x, ref y); + UserToDevice (ref x, ref y); } [Obsolete("Use UserToDeviceDistance instead")] public void TransformDistance (ref double dx, ref double dy) { - NativeMethods.cairo_user_to_device_distance (handle, ref dx, ref dy); + UserToDevice (ref dx, ref dy); } [Obsolete("Use DeviceToUser instead")] public void InverseTransformPoint (ref double x, ref double y) { - NativeMethods.cairo_device_to_user (handle, ref x, ref y); + UserToDevice (ref x, ref y); } [Obsolete("Use DeviceToUserDistance instead")] public void InverseTransformDistance (ref double dx, ref double dy) { - NativeMethods.cairo_device_to_user_distance (handle, ref dx, ref dy); + DeviceToUserDistance (ref dx, ref dy); } public void UserToDevice (ref double x, ref double y) { + CheckDisposed (); NativeMethods.cairo_user_to_device (handle, ref x, ref y); } public void UserToDeviceDistance (ref double dx, ref double dy) { + CheckDisposed (); NativeMethods.cairo_user_to_device_distance (handle, ref dx, ref dy); } public void DeviceToUser (ref double x, ref double y) { + CheckDisposed (); NativeMethods.cairo_device_to_user (handle, ref x, ref y); } public void DeviceToUserDistance (ref double dx, ref double dy) { + CheckDisposed (); NativeMethods.cairo_device_to_user_distance (handle, ref dx, ref dy); } public Matrix Matrix { set { + CheckDisposed (); NativeMethods.cairo_set_matrix (handle, value); } get { + CheckDisposed (); Matrix m = new Matrix (); NativeMethods.cairo_get_matrix (handle, m); return m; @@ -682,11 +775,13 @@ namespace Cairo { public void SetFontSize (double scale) { + CheckDisposed (); NativeMethods.cairo_set_font_size (handle, scale); } public void IdentityMatrix () { + CheckDisposed (); NativeMethods.cairo_identity_matrix (handle); } @@ -703,20 +798,28 @@ namespace Cairo { public Matrix FontMatrix { get { + CheckDisposed (); Matrix m; NativeMethods.cairo_get_font_matrix (handle, out m); return m; } - set { NativeMethods.cairo_set_font_matrix (handle, value); } + set { + CheckDisposed (); + NativeMethods.cairo_set_font_matrix (handle, value); + } } public FontOptions FontOptions { get { + CheckDisposed (); FontOptions options = new FontOptions (); NativeMethods.cairo_get_font_options (handle, options.Handle); return options; } - set { NativeMethods.cairo_set_font_options (handle, value.Handle); } + set { + CheckDisposed (); + NativeMethods.cairo_set_font_options (handle, value.Handle); + } } [StructLayout(LayoutKind.Sequential)] @@ -757,6 +860,8 @@ namespace Cairo { public void ShowGlyphs (Glyph[] glyphs) { + CheckDisposed (); + IntPtr ptr; ptr = FromGlyphToUnManagedMemory (glyphs); @@ -780,6 +885,8 @@ namespace Cairo { public void GlyphPath (Glyph[] glyphs) { + CheckDisposed (); + IntPtr ptr; ptr = FromGlyphToUnManagedMemory (glyphs); @@ -787,11 +894,11 @@ namespace Cairo { NativeMethods.cairo_glyph_path (handle, ptr, glyphs.Length); Marshal.FreeHGlobal (ptr); - } public FontExtents FontExtents { get { + CheckDisposed (); FontExtents f_extents; NativeMethods.cairo_font_extents (handle, out f_extents); return f_extents; @@ -800,6 +907,7 @@ namespace Cairo { public void CopyPage () { + CheckDisposed (); NativeMethods.cairo_copy_page (handle); } @@ -821,21 +929,25 @@ namespace Cairo { public FontFace GetContextFontFace () { + CheckDisposed (); return Cairo.FontFace.Lookup (NativeMethods.cairo_get_font_face (handle), false); } public void SetContextFontFace (FontFace value) { + CheckDisposed (); NativeMethods.cairo_set_font_face (handle, value == null ? IntPtr.Zero : value.Handle); } public void SelectFontFace (string family, FontSlant slant, FontWeight weight) { + CheckDisposed (); NativeMethods.cairo_select_font_face (handle, family, slant, weight); } public void ShowPage () { + CheckDisposed (); NativeMethods.cairo_show_page (handle); } @@ -860,26 +972,31 @@ namespace Cairo { public void ShowText (string str) { + CheckDisposed (); NativeMethods.cairo_show_text (handle, TerminateUtf8 (str)); } public void ShowText (byte[] utf8) { + CheckDisposed (); NativeMethods.cairo_show_text (handle, TerminateUtf8 (utf8)); } public void TextPath (string str) { + CheckDisposed (); NativeMethods.cairo_text_path (handle, TerminateUtf8 (str)); } public void TextPath (byte[] utf8) { + CheckDisposed (); NativeMethods.cairo_text_path (handle, TerminateUtf8 (utf8)); } public TextExtents TextExtents (string s) { + CheckDisposed (); TextExtents extents; NativeMethods.cairo_text_extents (handle, TerminateUtf8 (s), out extents); return extents; @@ -887,6 +1004,7 @@ namespace Cairo { public TextExtents TextExtents(byte[] utf8) { + CheckDisposed (); TextExtents extents; NativeMethods.cairo_text_extents (handle, TerminateUtf8 (utf8), out extents); return extents; @@ -894,6 +1012,8 @@ namespace Cairo { public TextExtents GlyphExtents (Glyph[] glyphs) { + CheckDisposed (); + IntPtr ptr = FromGlyphToUnManagedMemory (glyphs); TextExtents extents; @@ -911,7 +1031,10 @@ namespace Cairo { } public bool HasCurrentPoint { - get { return NativeMethods.cairo_has_current_point (handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_has_current_point (handle); + } } } } diff --git a/cairo/Device.cs b/cairo/Device.cs index 06d31c523..fb5dde557 100644 --- a/cairo/Device.cs +++ b/cairo/Device.cs @@ -41,11 +41,15 @@ namespace Cairo internal Device (IntPtr handle) { + if (handle == IntPtr.Zero) + throw new ArgumentException ("handle should not be NULL", "handle"); + this.handle = NativeMethods.cairo_device_reference (handle); } public Status Acquire () { + CheckDisposed (); return NativeMethods.cairo_device_acquire (handle); } @@ -57,27 +61,42 @@ namespace Cairo GC.SuppressFinalize (this); } + void CheckDisposed () + { + if (handle == IntPtr.Zero) + throw new ObjectDisposedException ("Object has already been disposed"); + } + public void Finish () { + CheckDisposed (); NativeMethods.cairo_device_finish (handle); } public void Flush () { + CheckDisposed (); NativeMethods.cairo_device_flush (handle); } public void Release () { + CheckDisposed (); NativeMethods.cairo_device_release (handle); } public Status Status { - get { return NativeMethods.cairo_device_status (handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_device_status (handle); + } } public DeviceType Type { - get { return NativeMethods.cairo_device_get_type (handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_device_get_type (handle); + } } } diff --git a/cairo/FontFace.cs b/cairo/FontFace.cs index 19d8163c3..b8ce89866 100644 --- a/cairo/FontFace.cs +++ b/cairo/FontFace.cs @@ -68,6 +68,12 @@ namespace Cairo handle = IntPtr.Zero; } + void CheckDisposed () + { + if (handle == IntPtr.Zero) + throw new ObjectDisposedException ("Object has already been disposed"); + } + [Obsolete] public FontFace (IntPtr handle) : this (handle, true) { @@ -75,6 +81,9 @@ namespace Cairo public FontFace (IntPtr handle, bool owned) { + if (handle == IntPtr.Zero) + throw new ArgumentException ("handle should not be NULL", "handle"); + this.handle = handle; if (!owned) NativeMethods.cairo_font_face_reference (handle); @@ -90,18 +99,23 @@ namespace Cairo public Status Status { get { + CheckDisposed (); return NativeMethods.cairo_font_face_status (handle); } } public FontType FontType { get { + CheckDisposed (); return NativeMethods.cairo_font_face_get_type (handle); } } public uint ReferenceCount { - get { return NativeMethods.cairo_font_face_get_reference_count (handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_font_face_get_reference_count (handle); + } } } } diff --git a/cairo/FontOptions.cs b/cairo/FontOptions.cs index 5269d54df..3c151c59d 100644 --- a/cairo/FontOptions.cs +++ b/cairo/FontOptions.cs @@ -45,6 +45,9 @@ namespace Cairo internal FontOptions (IntPtr handle) { + if (handle == IntPtr.Zero) + throw new ArgumentException ("handle should not be NULL", "handle"); + this.handle = handle; if (CairoDebug.Enabled) CairoDebug.OnAllocated (handle); @@ -52,6 +55,7 @@ namespace Cairo public FontOptions Copy () { + CheckDisposed (); return new FontOptions (NativeMethods.cairo_font_options_copy (handle)); } @@ -79,6 +83,12 @@ namespace Cairo handle = IntPtr.Zero; } + void CheckDisposed () + { + if (handle == IntPtr.Zero) + throw new ObjectDisposedException ("Object has already been disposed"); + } + public static bool operator == (FontOptions options, FontOptions other) { return Equals (options, other); @@ -112,31 +122,59 @@ namespace Cairo { if (other == null) throw new ArgumentNullException ("other"); + CheckDisposed (); NativeMethods.cairo_font_options_merge (handle, other.Handle); } public Antialias Antialias { - get { return NativeMethods.cairo_font_options_get_antialias (handle); } - set { NativeMethods.cairo_font_options_set_antialias (handle, value); } + get { + CheckDisposed (); + return NativeMethods.cairo_font_options_get_antialias (handle); + } + set { + CheckDisposed (); + NativeMethods.cairo_font_options_set_antialias (handle, value); + } } public HintMetrics HintMetrics { - get { return NativeMethods.cairo_font_options_get_hint_metrics (handle);} - set { NativeMethods.cairo_font_options_set_hint_metrics (handle, value); } + get { + CheckDisposed (); + return NativeMethods.cairo_font_options_get_hint_metrics (handle); + } + set { + CheckDisposed (); + NativeMethods.cairo_font_options_set_hint_metrics (handle, value); + } } public HintStyle HintStyle { - get { return NativeMethods.cairo_font_options_get_hint_style (handle);} - set { NativeMethods.cairo_font_options_set_hint_style (handle, value); } + get { + CheckDisposed (); + return NativeMethods.cairo_font_options_get_hint_style (handle); + } + set { + CheckDisposed (); + NativeMethods.cairo_font_options_set_hint_style (handle, value); + } } public Status Status { - get { return NativeMethods.cairo_font_options_status (handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_font_options_status (handle); + } } public SubpixelOrder SubpixelOrder { - get { return NativeMethods.cairo_font_options_get_subpixel_order (handle);} - set { NativeMethods.cairo_font_options_set_subpixel_order (handle, value); } + get { + CheckDisposed (); + return NativeMethods.cairo_font_options_get_subpixel_order (handle); + } + set { + CheckDisposed (); + NativeMethods.cairo_font_options_set_subpixel_order (handle, value); + } } } } diff --git a/cairo/Gradient.cs b/cairo/Gradient.cs index 0fb617e42..25bcef6d5 100644 --- a/cairo/Gradient.cs +++ b/cairo/Gradient.cs @@ -44,6 +44,7 @@ namespace Cairo { public int ColorStopCount { get { + CheckDisposed (); int cnt; NativeMethods.cairo_pattern_get_color_stop_count (Handle, out cnt); return cnt; @@ -52,12 +53,14 @@ namespace Cairo { public Status AddColorStop (double offset, Color c) { + CheckDisposed (); NativeMethods.cairo_pattern_add_color_stop_rgba (Handle, offset, c.R, c.G, c.B, c.A); return Status; } public Status AddColorStopRgb (double offset, Color c) { + CheckDisposed (); NativeMethods.cairo_pattern_add_color_stop_rgb (Handle, offset, c.R, c.G, c.B); return Status; } diff --git a/cairo/ImageSurface.cs b/cairo/ImageSurface.cs index 98143fe8e..3b0678e2a 100644 --- a/cairo/ImageSurface.cs +++ b/cairo/ImageSurface.cs @@ -70,11 +70,16 @@ namespace Cairo { } public int Width { - get { return NativeMethods.cairo_image_surface_get_width (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_image_surface_get_width (Handle); } } public int Height { - get { return NativeMethods.cairo_image_surface_get_height (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_image_surface_get_height (Handle); + } } public byte[] Data { @@ -89,16 +94,23 @@ namespace Cairo { public IntPtr DataPtr { get { + CheckDisposed (); return NativeMethods.cairo_image_surface_get_data (Handle); } } public Format Format { - get { return NativeMethods.cairo_image_surface_get_format (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_image_surface_get_format (Handle); + } } public int Stride { - get { return NativeMethods.cairo_image_surface_get_stride (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_image_surface_get_stride (Handle); + } } } } diff --git a/cairo/LinearGradient.cs b/cairo/LinearGradient.cs index 85fdea84a..477418f7f 100644 --- a/cairo/LinearGradient.cs +++ b/cairo/LinearGradient.cs @@ -44,6 +44,7 @@ namespace Cairo { public PointD[] LinearPoints { get { + CheckDisposed (); double x0, y0, x1, y1; PointD[] points = new PointD [2]; diff --git a/cairo/PSSurface.cs b/cairo/PSSurface.cs index 9d6b73be6..fa6382c43 100644 --- a/cairo/PSSurface.cs +++ b/cairo/PSSurface.cs @@ -43,21 +43,25 @@ namespace Cairo { public void BeginPageSetup () { + CheckDisposed (); NativeMethods.cairo_ps_surface_dsc_begin_page_setup (Handle); } public void BeginSetup () { + CheckDisposed (); NativeMethods.cairo_ps_surface_dsc_begin_setup (Handle); } public void DscComment (string comment) { + CheckDisposed (); NativeMethods.cairo_ps_surface_dsc_comment (Handle, comment); } public void SetSize (double width, double height) { + CheckDisposed (); NativeMethods.cairo_ps_surface_set_size (Handle, width, height); } } diff --git a/cairo/Path.cs b/cairo/Path.cs index f5007feb9..6e177fc20 100644 --- a/cairo/Path.cs +++ b/cairo/Path.cs @@ -40,6 +40,9 @@ namespace Cairo { internal Path (IntPtr handle) { + if (handle == IntPtr.Zero) + throw new ArgumentException ("handle should not be NULL", "handle"); + this.handle = handle; if (CairoDebug.Enabled) CairoDebug.OnAllocated (handle); diff --git a/cairo/Pattern.cs b/cairo/Pattern.cs index bc0a962a2..fa130ce65 100644 --- a/cairo/Pattern.cs +++ b/cairo/Pattern.cs @@ -64,6 +64,9 @@ namespace Cairo { internal Pattern (IntPtr handle, bool owned) { + if (handle == IntPtr.Zero) + throw new ArgumentException ("handle should not be NULL", "handle"); + Handle = handle; if (!owned) NativeMethods.cairo_pattern_reference (handle); @@ -85,6 +88,7 @@ namespace Cairo { [Obsolete] protected void Reference () { + CheckDisposed (); NativeMethods.cairo_pattern_reference (pattern); } @@ -106,6 +110,12 @@ namespace Cairo { Handle = IntPtr.Zero; } + protected void CheckDisposed () + { + if (Handle == IntPtr.Zero) + throw new ObjectDisposedException ("Object has already been disposed"); + } + [Obsolete ("Use Dispose()")] public void Destroy () { @@ -114,21 +124,32 @@ namespace Cairo { public Status Status { - get { return NativeMethods.cairo_pattern_status (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_pattern_status (Handle); + } } public Extend Extend { - get { return NativeMethods.cairo_pattern_get_extend (Handle); } - set { NativeMethods.cairo_pattern_set_extend (Handle, value); } + get { + CheckDisposed (); + return NativeMethods.cairo_pattern_get_extend (Handle); + } + set { + CheckDisposed (); + NativeMethods.cairo_pattern_set_extend (Handle, value); + } } public Matrix Matrix { set { + CheckDisposed (); NativeMethods.cairo_pattern_set_matrix (Handle, value); } get { + CheckDisposed (); Matrix m = new Matrix (); NativeMethods.cairo_pattern_get_matrix (Handle, m); return m; @@ -148,7 +169,10 @@ namespace Cairo { } public PatternType PatternType { - get { return NativeMethods.cairo_pattern_get_type (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_pattern_get_type (Handle); + } } } } diff --git a/cairo/PdfSurface.cs b/cairo/PdfSurface.cs index c980f249e..996485327 100644 --- a/cairo/PdfSurface.cs +++ b/cairo/PdfSurface.cs @@ -43,6 +43,7 @@ namespace Cairo { public void SetSize (double width, double height) { + CheckDisposed (); NativeMethods.cairo_pdf_surface_set_size (Handle, width, height); } } diff --git a/cairo/Region.cs b/cairo/Region.cs index cd0ba33fd..3142fc046 100644 --- a/cairo/Region.cs +++ b/cairo/Region.cs @@ -52,6 +52,9 @@ namespace Cairo public Region (IntPtr handle, bool owned) { + if (handle == IntPtr.Zero) + throw new ArgumentException ("handle should not be NULL", "handle"); + this.handle = handle; if (!owned) NativeMethods.cairo_region_reference (handle); @@ -75,6 +78,7 @@ namespace Cairo public Region Copy () { + CheckDisposed (); return new Region (NativeMethods.cairo_region_copy (Handle), true); } @@ -101,6 +105,12 @@ namespace Cairo handle = IntPtr.Zero; } + void CheckDisposed () + { + if (handle == IntPtr.Zero) + throw new ObjectDisposedException ("Object has already been disposed"); + } + public override bool Equals (object obj) { return (obj is Region) && NativeMethods.cairo_region_equal (Handle, (obj as Region).Handle); @@ -112,11 +122,14 @@ namespace Cairo } public Status Status { - get { return NativeMethods.cairo_region_status (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_region_status (Handle); } } public RectangleInt Extents { get { + CheckDisposed (); RectangleInt result; NativeMethods.cairo_region_get_extents (Handle, out result); return result; @@ -124,72 +137,90 @@ namespace Cairo } public int NumRectangles { - get { return NativeMethods.cairo_region_num_rectangles (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_region_num_rectangles (Handle); + } } public RectangleInt GetRectangle (int nth) { + CheckDisposed (); RectangleInt val; NativeMethods.cairo_region_get_rectangle (Handle, nth, out val); return val; } public bool IsEmpty { - get { return NativeMethods.cairo_region_is_empty (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_region_is_empty (Handle); + } } public RegionOverlap ContainsPoint (RectangleInt rectangle) { + CheckDisposed (); return NativeMethods.cairo_region_contains_rectangle (Handle, ref rectangle); } public bool ContainsPoint (int x, int y) { + CheckDisposed (); return NativeMethods.cairo_region_contains_point (Handle, x, y); } public void Translate (int dx, int dy) { + CheckDisposed (); NativeMethods.cairo_region_translate (Handle, dx, dy); } public Status Subtract (Region other) { + CheckDisposed (); return NativeMethods.cairo_region_subtract (Handle, other.Handle); } public Status SubtractRectangle (RectangleInt rectangle) { + CheckDisposed (); return NativeMethods.cairo_region_subtract_rectangle (Handle, ref rectangle); } public Status Intersect (Region other) { + CheckDisposed (); return NativeMethods.cairo_region_intersect (Handle, other.Handle); } public Status IntersectRectangle (RectangleInt rectangle) { + CheckDisposed (); return NativeMethods.cairo_region_intersect_rectangle (Handle, ref rectangle); } public Status Union (Region other) { + CheckDisposed (); return NativeMethods.cairo_region_union (Handle, other.Handle); } public Status UnionRectangle (RectangleInt rectangle) { + CheckDisposed (); return NativeMethods.cairo_region_union_rectangle (Handle, ref rectangle); } public Status Xor (Region other) { + CheckDisposed (); return NativeMethods.cairo_region_xor (Handle, other.Handle); } public Status XorRectangle (RectangleInt rectangle) { + CheckDisposed (); return NativeMethods.cairo_region_xor_rectangle (Handle, ref rectangle); } } diff --git a/cairo/ScaledFont.cs b/cairo/ScaledFont.cs index 937194607..179bbe5bc 100644 --- a/cairo/ScaledFont.cs +++ b/cairo/ScaledFont.cs @@ -34,6 +34,9 @@ namespace Cairo { internal ScaledFont (IntPtr handle, bool owner) { + if (handle == IntPtr.Zero) + throw new ArgumentException ("handle should not be NULL", "handle"); + this.handle = handle; if (!owner) NativeMethods.cairo_scaled_font_reference (handle); @@ -59,6 +62,7 @@ namespace Cairo { public FontExtents FontExtents { get { + CheckDisposed (); FontExtents extents; NativeMethods.cairo_scaled_font_extents (handle, out extents); return extents; @@ -67,6 +71,7 @@ namespace Cairo { public Matrix FontMatrix { get { + CheckDisposed (); Matrix m; NativeMethods.cairo_scaled_font_get_font_matrix (handle, out m); return m; @@ -75,12 +80,14 @@ namespace Cairo { public FontType FontType { get { + CheckDisposed (); return NativeMethods.cairo_scaled_font_get_type (handle); } } public TextExtents GlyphExtents (Glyph[] glyphs) { + CheckDisposed (); IntPtr ptr = Context.FromGlyphToUnManagedMemory (glyphs); TextExtents extents; @@ -92,7 +99,10 @@ namespace Cairo { public Status Status { - get { return NativeMethods.cairo_scaled_font_status (handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_scaled_font_status (handle); + } } public void Dispose () @@ -113,9 +123,16 @@ namespace Cairo { handle = IntPtr.Zero; } + void CheckDisposed () + { + if (handle == IntPtr.Zero) + throw new ObjectDisposedException ("Object has already been disposed"); + } + [Obsolete] protected void Reference () { + CheckDisposed (); NativeMethods.cairo_scaled_font_reference (handle); } } diff --git a/cairo/SolidPattern.cs b/cairo/SolidPattern.cs index 875b3fbf1..c435b67d8 100644 --- a/cairo/SolidPattern.cs +++ b/cairo/SolidPattern.cs @@ -62,6 +62,7 @@ namespace Cairo { public Color Color { get { + CheckDisposed (); double red, green, blue, alpha; NativeMethods.cairo_pattern_get_rgba (Handle, out red, out green, out blue, out alpha); return new Color (red, green, blue, alpha); diff --git a/cairo/Surface.cs b/cairo/Surface.cs index 6fa8c0209..c1411e1e5 100644 --- a/cairo/Surface.cs +++ b/cairo/Surface.cs @@ -51,12 +51,15 @@ namespace Cairo { } [Obsolete] - protected Surface (IntPtr ptr) : this (ptr, true) + protected Surface (IntPtr handle) : this (handle, true) { } protected Surface (IntPtr handle, bool owner) { + if (handle == IntPtr.Zero) + throw new ArgumentException ("handle should not be NULL", "handle"); + this.handle = handle; if (!owner) NativeMethods.cairo_surface_reference (handle); @@ -151,24 +154,34 @@ namespace Cairo { handle = IntPtr.Zero; } + protected void CheckDisposed () + { + if (handle == IntPtr.Zero) + throw new ObjectDisposedException ("Object has already been disposed"); + } + public Status Finish () { + CheckDisposed (); NativeMethods.cairo_surface_finish (handle); return Status; } public void Flush () { + CheckDisposed (); NativeMethods.cairo_surface_flush (handle); } public void MarkDirty () { + CheckDisposed (); NativeMethods.cairo_surface_mark_dirty (Handle); } public void MarkDirty (Rectangle rectangle) { + CheckDisposed (); NativeMethods.cairo_surface_mark_dirty_rectangle (Handle, (int)rectangle.X, (int)rectangle.Y, (int)rectangle.Width, (int)rectangle.Height); } @@ -180,12 +193,14 @@ namespace Cairo { public PointD DeviceOffset { get { + CheckDisposed (); double x, y; NativeMethods.cairo_surface_get_device_offset (handle, out x, out y); return new PointD (x, y); } set { + CheckDisposed (); NativeMethods.cairo_surface_set_device_offset (handle, value.X, value.Y); } } @@ -198,11 +213,13 @@ namespace Cairo { public void SetFallbackResolution (double x, double y) { + CheckDisposed (); NativeMethods.cairo_surface_set_fallback_resolution (handle, x, y); } public void WriteToPng (string filename) { + CheckDisposed (); NativeMethods.cairo_surface_write_to_png (handle, filename); } @@ -214,19 +231,29 @@ namespace Cairo { } public Status Status { - get { return NativeMethods.cairo_surface_status (handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_surface_status (handle); + } } public Content Content { - get { return NativeMethods.cairo_surface_get_content (handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_surface_get_content (handle); + } } public SurfaceType SurfaceType { - get { return NativeMethods.cairo_surface_get_type (handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_surface_get_type (handle); + } } public uint ReferenceCount { - get { return NativeMethods.cairo_surface_get_reference_count (handle); } + get { + return NativeMethods.cairo_surface_get_reference_count (handle); } } } } diff --git a/cairo/SurfacePattern.cs b/cairo/SurfacePattern.cs index 5ba188fe1..a47ca13e5 100644 --- a/cairo/SurfacePattern.cs +++ b/cairo/SurfacePattern.cs @@ -43,8 +43,14 @@ namespace Cairo { } public Filter Filter { - set { NativeMethods.cairo_pattern_set_filter (Handle, value); } - get { return NativeMethods.cairo_pattern_get_filter (Handle); } + set { + CheckDisposed (); + NativeMethods.cairo_pattern_set_filter (Handle, value); + } + get { + CheckDisposed (); + return NativeMethods.cairo_pattern_get_filter (Handle); + } } } } diff --git a/cairo/SvgSurface.cs b/cairo/SvgSurface.cs index 418295011..ad0d7bcb0 100644 --- a/cairo/SvgSurface.cs +++ b/cairo/SvgSurface.cs @@ -43,6 +43,7 @@ namespace Cairo { public void RestrictToVersion (SvgVersion version) { + CheckDisposed (); NativeMethods.cairo_svg_surface_restrict_to_version (Handle, version); } } diff --git a/cairo/XcbSurface.cs b/cairo/XcbSurface.cs index 142ebf9e3..be025d343 100644 --- a/cairo/XcbSurface.cs +++ b/cairo/XcbSurface.cs @@ -48,6 +48,7 @@ namespace Cairo { public void SetSize (int width, int height) { + CheckDisposed (); NativeMethods.cairo_xcb_surface_set_size (Handle, width, height); } } diff --git a/cairo/XlibSurface.cs b/cairo/XlibSurface.cs index c0003a491..cd1935927 100644 --- a/cairo/XlibSurface.cs +++ b/cairo/XlibSurface.cs @@ -55,40 +55,63 @@ namespace Cairo { public void SetDrawable (IntPtr drawable, int width, int height) { + CheckDisposed (); NativeMethods.cairo_xlib_surface_set_drawable (Handle, drawable, width, height); } public void SetSize (int width, int height) { + CheckDisposed (); NativeMethods.cairo_xlib_surface_set_size (Handle, width, height); } public int Depth { - get { return NativeMethods.cairo_xlib_surface_get_depth (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_xlib_surface_get_depth (Handle); + } } public IntPtr Display { - get { return NativeMethods.cairo_xlib_surface_get_display (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_xlib_surface_get_display (Handle); + } } public IntPtr Drawable { - get { return NativeMethods.cairo_xlib_surface_get_drawable (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_xlib_surface_get_drawable (Handle); + } } public int Height { - get { return NativeMethods.cairo_xlib_surface_get_height (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_xlib_surface_get_height (Handle); + } } public IntPtr Screen { - get { return NativeMethods.cairo_xlib_surface_get_screen (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_xlib_surface_get_screen (Handle); + } } public IntPtr Visual { - get { return NativeMethods.cairo_xlib_surface_get_visual (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_xlib_surface_get_visual (Handle); + } } public int Width { - get { return NativeMethods.cairo_xlib_surface_get_width (Handle); } + get { + CheckDisposed (); + return NativeMethods.cairo_xlib_surface_get_width (Handle); + } } }