[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.
Thanks,
Govind.
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