[cairo] Problems erasing a line.

Govind Salinas govindsalinas at gmail.com
Mon Mar 19 19:05:29 PDT 2007

This makes some sense, I actually thought the antialiasing might have
something to do with it tried to disable it by setting the Antialias
property to None.  That didn't work but I will give this a try and see
what happens.


On Mon, 2007-03-19 at 12:13 +0300, Justin Carlson wrote:
> Hi Gorvind.  I'm not a deep cairo hacker, but I'll try to answer your 
> questions.  I'm sure someone else will correct me when I invariably go 
> wrong.  :)
> Govind Salinas wrote:
> > Hey guys,
> >
> > I am writing a small project to familiarize myself with c# and all the
> > new stuff that has come into the gnome-related world lately,
> > specifically Cairo.  One thing I was trying to do was make a
> > Gtk.DrawingArea.  When I get a left mouse click I start a rubber band
> > line to the current mouse location (mouse move events).  As the cursor
> > moves, I white out my background, erase my old line and draw a new one.
> > However I keep seeing artifacts of my previous line.
> >
> > Here is the relevant code:
> >
> >   
> ...snip
> > This more or less works other than I get artifacts of previous lines.
> >   
> Without seeing the rest of your code, it's hard to say exactly what's 
> going on.  I suspect your problem here is related what you've seen in 
> the second code snippet, which I've addressed below.  One other place 
> you can easily go wrong is not realizing that, when you invalidate a 
> section of a widget to force a redraw in GTK+, the expose event that 
> comes back automatically clips the area to be drawn to the invalidated 
> region.  So if you aren't careful in what you invalidate, you can end up 
> leaving artifacts.  To figure out exactly what to invalidate, you either 
> have to be very careful in how you draw, or you should use 
> cairo_{stroke|fill}_extents (or whatever the equivalent is in the C# 
> bindings) to figure out the precise area that's gone wrong.
> > As an experiment I tried this:
> >   
> ...snip...
> > What I get from this is the outside of the line I was drawing (I
> > successfully erased the middle of the line but left two thinner lines in
> > its place).  I would expect that this leaves me with a blank canvas.  Is
> > there some fundamental thing that I am missing that will get this to
> > work?  The only way I have gotten this to draw cleanly is to invalidate
> > the whole area (QueueDraw() for example) and then draw the new line.
> > While this works its seems like an expensive way to erase a line.  Can
> > someone tell me where I am going wrong?
> >   
> This counter-intuitive result can come about whenever you have some 
> transparency, which, when drawing lines, is virtually always in cairo.  
> Whenever you have transparency, the result will be some of what you're 
> painting, and some of what was previously there.  So if you draw a white 
> line on a black background, you get white in the middle of the line, and 
> gray at the antialiased edges.  Let's say that the value of one 
> particular edge pixel is  .5 * black + .5 * white. 
> So if you then draw the same line again, only in black, the pixel is 
> rendered as .5 * (.5 * black + .5 * white) + .5 * black. 
> Plug in whatever values you want for black and white, and you'll see 
> that those edge pixels are not actually black.
> The only situation in line drawing in cairo in which you don't get 
> antialiased pixels is (I believe) when you have a (post-scaling) 
> integral stroke width, your coordinates in device space all end in .5, 
> and your lines are completely horizontal or vertical.  e.g. (and I'm 
> guessing at the C# binding syntax here:)
> gr.SetMatrix(identity);
> gr.SetStrokeWidth(1.0);
> gr.SetColor(Black);
> gr.Rectangle(10.5, 10.5, 20, 20);
> gr.Stroke();
> should give you a pure 1 pixel wide rectangle that has no transparent 
> pixels.
> Hope that helps!
> -J

More information about the cairo mailing list