[cairo] How to exactly overwrite anti-aliased shapes?

Josh Sanford xrjoshs at gmail.com
Fri Sep 16 12:55:28 UTC 2016


[I previously posted this on stackoverflow, but that appears not to be the
best forum for the question.]

While using Cairo 1.14.6 for display purposes, I found that overwriting the
very same path with another color does not necessarily overwrite all
pixels, and leaves undesirable artifacts behind.

As evidence of my claim I offer this output from a short self-contained
example, the source for which follows further below.

[image: enter image description here] <http://i.stack.imgur.com/QBXjh.png>

An explanation of the six parts of the image, from left to right:

   1. Original shape stroked in blue.
   2. Original shape overwritten in RGBA white.
   3. Original shape overwritten in RGB white.
   4. Original shape overwritten in RGBA white with CAIRO_OPERATOR_SOURCE
   mode.
   5. Original shape overwritten in RGBA white with CAIRO_OPERATOR_SOURCE
   mode and CAIRO_ANTIALIAS_NONE.
   6. Original shape overwritten in RGBA white with CAIRO_OPERATOR_SOURCE
   mode and CAIRO_ANTIALIAS_BEST.

The image was generated from the following code:

#include "cairo/cairo.h"
#define M_PI 3.14159265358979323846
void draw_shape(cairo_t* cr, int x, int y) {
    cairo_arc(cr, 50 + x, 50 + y, 48, -M_PI, -M_PI / 2);
    cairo_stroke(cr);
    cairo_move_to(cr, x + 2, y + 2);
    cairo_line_to(cr, x + 48, y + 48);
    cairo_stroke(cr);}
int main(int argc, char** argv) {
    int x = 0;
    int y = 0;
    cairo_surface_t* surface =
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 300, 50);
    cairo_t* cr = cairo_create(surface);

    /* Draw a white background and a few shapes to overwrite */
    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
    cairo_paint(cr);
    cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 1.0);
    draw_shape(cr, x, y); x += 50;
    draw_shape(cr, x, y); x += 50;
    draw_shape(cr, x, y); x += 50;
    draw_shape(cr, x, y); x += 50;
    draw_shape(cr, x, y); x += 50;
    draw_shape(cr, x, y); x += 50;
    x = 50;

    /* Leftmost shape is left unchanged for reference */

    /* Stroke in RGBA opaque white */
    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
    draw_shape(cr, x, y); x += 50;

    /* Stroke in RGB white */
    cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
    draw_shape(cr, x + 0, y); x += 50;

    /* Stroke in opaque white without blending */
    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
    cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
    draw_shape(cr, x, y); x += 50;

    /* Stroke in opaque white without blending, with no antialiasing */
    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
    cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
    cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
    draw_shape(cr, x, y); x += 50;

    /* Stroke in opaque white without blending, with best antialiasing */
    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
    cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
    cairo_set_antialias(cr, CAIRO_ANTIALIAS_BEST);
    draw_shape(cr, x, y); x += 50;

    /* Write the results to a file */
    cairo_surface_write_to_png(surface, "output.png");

    return 0;}

It doesn't make intuitive sense to me that overwriting the very same shape
would not overwrite all of its pixels, especially if I force it into
non-blending CAIRO_OPERATOR_SOURCE mode. The results are the same on the
framebuffer that constitutes my actual surface, so this is not an issue
with the backend.

Cairo is usually so good at what it does that I'm very surprised at this.
Is there no way to overwrite an anti-aliased shape exactly in Cairo?

Josh
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.cairographics.org/archives/cairo/attachments/20160916/b53af191/attachment-0001.html>


More information about the cairo mailing list