[cairo] Invert colors but without touching transparent parts

Mihai Moldovan ionic at ionic.de
Sun Sep 18 22:55:59 UTC 2022


Hi


I'm trying to invert colors from a previous drawing operation, but without
touching transparent parts.

I've tried painting with a white, opaque source and using the DIFFERENCE
operator, but that also inverts transparent elements (because the alpha
calculating is done using the logic implemented in the OVER operator?)

Is there any way to do what I have in mind?

I'm "attaching" (really inlining) a MWE to showcase the issue. I'd like to
invert the color of the rectangle from white to black, but keep the background
green. The actual thing I'm trying to do is more complicated, since it involves
reading an image into a GtkImage widget and modifying that in the draw function,
so using a mask is difficult to impossible (I initially thought of using the
internal pixbuf as a mask, but I don't know where GtkImage will actually draw
the pixbuf to, so that's not really a usable workaround).

Is what I want to do even possible? I'm not sure if transparency information
actually survive drawing operations (i.e., whether drawing operations just blend
source and destination and eventually create a fully opaque result or whether
transparency is passed-through).



Mihai


// valac --pkg gtk+-3.0 mwe-draw.vala

class App {
    public static int main (string[] argv) {
        // Create a new application
        var app = new Gtk.Application ("com.example.GtkApplication",
                                       GLib.ApplicationFlags.FLAGS_NONE);

        app.activate.connect (() => {
            // Create a new window.
            var window = new Gtk.ApplicationWindow (app);
            var window_style_ctx = window.get_style_context ();
            var bg_style = new Gtk.CssProvider ();
            bg_style.load_from_data ("* {background-color: #0F0;
                                      }", -1);
            window_style_ctx.add_provider (bg_style,
                Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);

            var drawing_area = new Gtk.DrawingArea ();
            drawing_area.draw.connect ((c) => {
                var color = Gdk.RGBA ();
                color.parse ("rgba (255, 255, 255, 1.0)");
                debug (color.to_string ());

                c.save ();
                c.set_source_rgba (0.0, 0.0, 0.0, 0.0);
                c.fill ();
                c.paint ();
                c.restore ();

                c.save ();
                c.set_source_rgba (color.red, color.green, color.blue,
                                   color.alpha);
                c.rectangle (20, 40, 100, 100);
                c.stroke_preserve ();
                c.fill ();
                c.restore ();

                c.set_source_rgb (1.0, 1.0, 1.0);
                c.set_operator (Cairo.Operator.DIFFERENCE);
                c.paint ();

                return false;
            });
            drawing_area.set_size_request (400, 300);
            drawing_area.show ();
            window.add (drawing_area);

            window.present ();
        });

        return app.run (argv);
    }
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <https://lists.cairographics.org/archives/cairo/attachments/20220919/636b6b6f/attachment.sig>


More information about the cairo mailing list