[cairo] Avoiding seams (again)

Timothée Lecomte timothee.lecomte at ens.fr
Wed Mar 22 15:34:59 PST 2006


> On Wed, 22 Mar 2006 22:13:56 +0100 (CET), Timothée Lecomte wrote:
>>
>> Do you remember the thread about avoiding seams between paths a months
>> ago ?
>
> I do. I think it's an interesting class of problem.
>
>> - stroke each path
>>  Good : gives expected result
>
> I'd like to disagree on that point. Stroking each shape will still
> introduce seams if there is transparency involved. And even with
> entirely opaque objects can result in "lumpiness" (that is,
> poor-quality antialiasing), on the border of the composite object,
> where multiple primitives meet.

I think I understand. These antialiasing problems are definitely more
complicated that I would have imagine.

>> - use CAIRO_OPERATOR_SATURATE
>>  Good : no seam, reasonably fast
>
> Those are looking like some good characteristics to work from as a
> starting point.

Indeed, but remember that this is still sub-optimal as it implies a
separate context and drawing front-to-back...

>>  Problem : have to draw front-to-back to a separate context whereas
>> gnuplot gives me the instructions back-to-front, so it adds some
>> overhead.
>> But  I also get white lines artifacts.
>> See : http://tipote.free.fr/wxt-saturate2.png
>>
>> Do you have other ideas, or a solution to the artefacts problem with
>> CAIRO_OPERATOR_SATURATE ?
>
> It could be just a bug that we hadn't noticed before. I'm not sure
> that the SATURATE stuff has seen a lot of correctness testing yet.
>
> If you could replicate this behavior in as minimal a test case as
> possible, that would be very helpful.

Sure. You made me try with both the image surface and the xlib one
(through gtk_cairo_create(), and the artefacts only appear with the xlib
surface.

Here is a sample code (plot.cr is the main context, plot.current_xmax and
plot.currentymax are its width and height):

	cairo_t *context;
	cairo_surface_t *surface;
	surface = cairo_surface_create_similar(cairo_get_target(plot.cr),
                                             CAIRO_CONTENT_COLOR_ALPHA,
                                             plot.current_xmax,
                                             plot.current_ymax);
	context = cairo_create(surface);
	cairo_set_operator(context,CAIRO_OPERATOR_SATURATE);

	cairo_move_to(context, 300, 200);
	cairo_rel_line_to(context, 100, 0);
	cairo_rel_line_to(context, 0, 100);
	cairo_close_path(context);
	cairo_set_source_rgb(context,0,0,0);
	cairo_fill(context);

	cairo_move_to(context, 250, 170);
	cairo_rel_line_to(context, 100, 0);
	cairo_rel_line_to(context, 0, 100);
	cairo_close_path(context);
	cairo_set_source_rgb(context,0,0,0.5);
	cairo_fill(context);

	cairo_move_to(context, 360, 200);
	cairo_rel_line_to(context, 30, 0);
	cairo_rel_line_to(context, 0, -40);
	cairo_close_path(context);
	cairo_set_source_rgb(context,1,0,0);
	cairo_fill(context);

	cairo_move_to(context, 400, 100);
	cairo_rel_line_to(context, 100, 0);
	cairo_rel_line_to(context, -100, 300);
	cairo_close_path(context);
	cairo_set_source_rgb(context,0,1,0);
	cairo_fill(context);

	cairo_move_to(context, 400, 300);
	cairo_rel_line_to(context, -80, -80);
	cairo_rel_line_to(context, 0, 100);
	cairo_close_path(context);
	cairo_set_source_rgb(context,0.6,0.4,0);
	cairo_fill(context);

	cairo_pattern_t *pattern = cairo_pattern_create_for_surface( surface );
	cairo_destroy( context );

	cairo_surface_destroy( surface );
	cairo_set_source( plot.cr, pattern );
	cairo_pattern_destroy( pattern );
	cairo_paint(plot.cr);

Here is the results :
For the xlib surface : http://tipote.free.fr/wxt-saturate3.png
For the image surface : http://tipote.free.fr/wxt-saturate4.png

Notice the edges between the blue, back and brown triangles.

Best regards,

Timothée






More information about the cairo mailing list