[Mono-list] Expose / Cairo not working properly?

Pupeno pupeno at pupeno.com
Sat Feb 24 10:05:20 EST 2007


Hello,
I have a problem with Cairo and Expose events. I am trying to make a custom 
widget. I need a canvas ta draw on. If there's a different way to achieve it, 
please, tell me.
First, the example in 
http://www.go-mono.com/docs/monodoc.ashx?link=T%3aCairo.Context seems not to 
work, when I hide and un-hide the app it works correctly, but move a smaller 
window over it and it doesn't re-draw itself. Is this a problem in my 
workstation, does anybody else see this same problem?
Based on that example and on a Python implementation of the same thing I wrote 
the code (at the bottom) that draws a pentagram. This has a deeper problem. 
It redraws itself incorrectly. It seems like when. It seems like if the part 
exposed gets re-drawn, but the coordinate system is moved from 0,0 to x,y 
where x,y is where the exposing starts. It's hard to explain, I'll attach a 
screenshot.
Any help is appreciated.
-- 
Pupeno <pupeno at pupeno.com> (http://pupeno.com)

PS: The code:

namespace ScoreReadingTrainer {
	public enum Clef {
		G, F, C3, C4
	}
	
	public class Score: Gtk.DrawingArea {
		// Margin, in %, on the left of the score (right has no margin).
		readonly private byte margin = 2;
		
		readonly private byte steps = 24;
		
		private Clef clef;
		
		public Score() {
			this.clef = Clef.G;
			this.ExposeEvent += Draw;
		}

		void Draw(object o, Gtk.ExposeEventArgs e) {
			Score score = o as Score;
			if(score != null) { // Either it is a Score or we are in problems.
				Cairo.Context context = Gdk.Context.CreateDrawable(score.GdkWindow);
				this.Draw(context, e.Event.Area.X, e.Event.Area.Y, e.Event.Area.Width, 
e.Event.Area.Height);
			}
		}
		
		void Draw(Cairo.Context context, int x, int y, int width, int height) {
			context.Rectangle(x, y, width, height);
			context.Clip();
			this.Draw(context);
		}
		
		void Draw(Cairo.Context context) {
			int width = this.Allocation.Width;
			int height = this.Allocation.Height;
			int realMargin = this.margin * width / 100;
			
			Console.WriteLine("{0}: width={1}, height={2}", System.DateTime.Now, width, 
height);
			
			// Paint a white background.
			context.Save();
			context.Color = new Cairo.Color(1,1,1);
			context.Paint();
			context.Restore();
			
			// Draw the pentagram.
			context.Save();
			context.Color = new Cairo.Color(0, 0, 0); // TODO: maybe use 0.2, 0.2, 0.2.
			context.LineWidth = height / 200;         // Make a relative line width so 
we don't end up with a lines too fat or too thin.
			if(context.LineWidth < 1) {               // Ensure that lines
				context.LineWidth = 1;                  // are at least one pixel wide.
			}
			for(int line = -2; line <= 2; line++) {// line in self.lines:
				double y = this.stepToPixels(line);
				if(context.LineWidth == 1) {            // Ensure that if lines are one 
pixel wide
					y += 0.5;                             // they will be one full pixel and 
not two half pixels: http://cairographics.org/FAQ
				}
				Console.WriteLine("{0}: Line {1} at {2} of width {3}.", 
System.DateTime.Now, line, y, context.LineWidth);
				context.MoveTo(realMargin, y);
				context.LineTo(width, y);
				context.Stroke();
			}
			context.Restore();
		}
    
		int stepToPixels(int step) {
			// """ Having the step number, return the pixel. A step is the minimum 
possible separations between notes, vertically."""
			int height = this.Allocation.Height;
			int middle = height / 2;
			int stepDistance = height / this.steps;
			return middle - step * stepDistance;
		}
	}
}

namespace Gdk {
	public class Context {
		//Use [DllImport("libgdk-win32-2.0-0.dll")] for  Win32 
		[DllImport("libgdk-x11-2.0.so")]
			internal static extern IntPtr gdk_x11_drawable_get_xdisplay(IntPtr raw);

		[DllImport("libgdk-x11-2.0.so")]
			internal static extern IntPtr gdk_x11_drawable_get_xid(IntPtr raw);

		[DllImport("libgdk-x11-2.0.so")]
			internal static extern IntPtr gdk_drawable_get_visual(IntPtr raw);

		[DllImport("libgdk-x11-2.0.so")]
			internal static extern IntPtr gdk_x11_visual_get_xvisual(IntPtr raw);

		public static Cairo.Context CreateDrawable(Gdk.Drawable drawable) {
			IntPtr x_drawable = IntPtr.Zero;
			int x_off = 0, y_off = 0;

			int x, y, w, h, d;
			((Gdk.Window)drawable).GetGeometry(out x, out y, out w, out h, out d);

			if(drawable is Gdk.Window) {
				((Gdk.Window) drawable).GetInternalPaintInfo(out drawable, out x_off, out 
y_off);
			}

			x_drawable = drawable.Handle;
			IntPtr visual = gdk_drawable_get_visual(x_drawable);

			IntPtr Xdisplay = gdk_x11_drawable_get_xdisplay(x_drawable);
			IntPtr Xvisual = gdk_x11_visual_get_xvisual(visual);
			IntPtr Xdrawable = gdk_x11_drawable_get_xid(x_drawable);

			Cairo.XlibSurface s = new Cairo.XlibSurface(Xdisplay, Xdrawable, Xvisual, 
w, h);

			Cairo.Context g = new Cairo.Context(s);

			if(drawable is Gdk.Window){
				g.Translate(-(double)x_off,-(double)y_off);
			}
			return g;
		}
	}
} 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: correct.png
Type: image/png
Size: 1165 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-list/attachments/20070224/386eb3a4/attachment.png 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: scrambled.png
Type: image/png
Size: 1348 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-list/attachments/20070224/386eb3a4/attachment-0001.png 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-list/attachments/20070224/386eb3a4/attachment.bin 


More information about the Mono-list mailing list