Re: How To: Render 1bpp bitmaps with cairo



I just answered to you on the cairo list. The messages on this list
give some more context, so I'll answer to the issues raised here on
this list. Please pick a list to reply to and we'll stick there.

2011/7/11 Mark Leisher <mleisher math nmsu edu>:
> It took a couple days, but I finally pieced together the necessary steps.
>
> The idea is to render a 1bpp bitmap either normally or selected (in the
> current background color on a rectangle painted with the current foreground
> color).
>
> You may need to fiddle with the GtkStateFlags depending on what type of
> widget you are drawing on (widget may be in a state other than NORMAL).

You're supposed to get the flags from the widget, not hardcode them in
the source.

> If anyone has a more elegant solution, please feel free to show it off.

Cairo does have an XOR operator.
Other than that you could do something like:

cairo_set_source_rgb(bg)
cairo_set_operator(source)
if (inverted)
  cairo_mask_surface(s)
cairo_paint()

cairo_set_source_rgb(fg)
if(!inverted)
  cairo_mask_surface(s)
else
  cairo_set_operator(out)
cairo_paint()

The disadvantage of this method is that it depends on the drawingarea
surface initally being completely transparent and will most likely
perform worse than your solution. But it does draw the colors always
in the same order and I guess that was the simplifaction you were
looking for.

===================================================================
>
> /*
>  * The 'data' parameter is a GtkDrawingArea widget.
>  */
>
> static gboolean invert = TRUE;
> static cairo_surface_t *s;
>
> /*
>  * Function type just to simplify the code.
>  */
> typedef void (*get_color_func_t)(GtkStyleContext *,GtkStateFlags,GdkRGBA *);
>
> static void
> invert_bitmap(GtkWidget *w, gpointer data)
> {
>    cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(GTK_WIDGET(data)));
>    GtkStyleContext *ctx = gtk_widget_get_style_context(GTK_WIDGET(data));
>    GdkRGBA c;
>    get_color_func_t get_bg, get_fg;
>
>    if (invert) {
>        /*
>         * Display inverted form: background of rectangle in foreground color
>         * and bitmap in background color.
>         */
>        get_bg = gtk_style_context_get_color;
>        get_fg = gtk_style_context_get_background_color;
>    } else {
>        /*
>         * Show normal bitmap while clearing the background behind it.
>         */
>        get_fg = gtk_style_context_get_color;
>        get_bg = gtk_style_context_get_background_color;
>    }
>
>    (*get_bg)(ctx,GTK_STATE_FLAG_NORMAL,&c);
>    cairo_set_source_rgb(cr,c.red,c.green,c.blue);
>    cairo_rectangle(cr, 1, 1, 13, 22);

Why are you offsetting the rectangle by 1x1 pixels?

>    cairo_fill(cr);
>
>    (*get_fg)(ctx,GTK_STATE_FLAG_NORMAL,&c);
>    cairo_set_source_rgb(cr,c.red,c.green,c.blue);
>    cairo_mask_surface(cr,s,2.0,1.0);

Why are you offsetting the mask by 2x1 pixels?

>    cairo_destroy(cr);
>    invert = !invert;
> }
>
> --
> Mark Leisher

Maarten


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]