Use operator without removing the background in Cairo

757 views Asked by At

I want to draw only a limited part of a cairo path, especially (but not limited to) text. So I looked at operators and tried the DEST_IN operator.

Consider the following example code

#include <cairo/cairo.h>

int main (int argc, char *argv[])
{
        cairo_surface_t *surface =
            cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 300, 300);
        cairo_t *cr = cairo_create (surface);

        //black background
        cairo_set_source_rgb(cr, 0, 0, 0);
        cairo_paint(cr);

        //blue text
        cairo_set_source_rgb(cr, 0, 0, 1);
        cairo_set_font_size(cr, 50);
        cairo_move_to(cr, 75, 160);
        cairo_text_path(cr, "foobar");
        cairo_fill(cr);

        //this should remove all parts of the blue text that
        //is not in the following rectangle
        cairo_set_operator(cr, CAIRO_OPERATOR_DEST_IN);
        cairo_rectangle(cr, 125, 125, 50, 50);
        cairo_fill(cr);

        cairo_destroy (cr);
        cairo_surface_write_to_png (surface, "output.png");
        cairo_surface_destroy (surface);
        return 0;
}

this is how the output looks:

enter image description here

The operator works, but not as expected (that was: only the part of the text inside the drawn 50x50 rectangle is displayed, but the rest of the background is untouched). Instead, the whole background (excepted for the rectangle area) is removed, and the picture becomes transparent.

Consider the black background to be any arbitrary complex drawing. Is there a way to use the operation as desired (extract a range from a path), without deleting any part of the background?

Is there a better way to cut a path, so only parts inside a provided rectangle are drawn?

1

There are 1 answers

1
Uli Schlachter On BEST ANSWER

How would cairo know which part is your "arbitrary complex drawing" (which you want to keep) and your blue text (which you want to partly erase)?

How about something like this? (Untested!):

#include <cairo/cairo.h>

int main (int argc, char *argv[])
{
        cairo_surface_t *surface =
            cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 300, 300);
        cairo_t *cr = cairo_create (surface);

        //black background
        cairo_set_source_rgb(cr, 0, 0, 0);
        cairo_paint(cr);

        // Redirect drawing to a temporary surface
        cairo_push_group(cr);

        //blue text
        cairo_set_source_rgb(cr, 0, 0, 1);
        cairo_set_font_size(cr, 50);
        cairo_move_to(cr, 75, 160);
        cairo_text_path(cr, "foobar");
        cairo_fill(cr);

        // Draw part of the blue text
        cairo_pop_group_to_source(cr);
        cairo_rectangle(cr, 125, 125, 50, 50);
        cairo_fill(cr);

        cairo_destroy (cr);
        cairo_surface_write_to_png (surface, "output.png");
        cairo_surface_destroy (surface);
        return 0;
}