[cairo] Howto draw ontop of a surface buffer

Daniel Bessler daniel.bessler at gmx.net
Wed Jan 24 09:02:17 PST 2007


Hi there!
I am coding since some time on kiba-dock (a gnome dock based on Kristian 
Høgsberg physics engine akamaru)
I integrated some days ago glitz support. before every icon on the dock had 
its own window, and i drawed the surface buffer, with the SOURCE operator on 
a offscreen pixmap, then i was able to use the ATOP operator for prelighting 
or blending only the content of the surface buffer. Now i use only one big 
surface for drawing and i draw the surface buffer with the OVER operator on 
the drawing surface, surely prelight and blending doesnt work anymore with 
the ATOP operator, it paints on all previosly rendered icons and the dock. I 
didnt found a solution, in all examples i found that the prelight on a bigger 
surface was handled by creating a rectangle and then calling cairo_fill, but 
i only wanna draw ontop of the surface buffer, and i dont wanna redraw the 
icon, what is the proper way to solve this problem?
The only workaround i can imagine is to create a surface, paint the surface 
buffer with the SOURCE operator on it, then i can prelight the icon with the 
ATOP operator, and then i paint the newly created surface with the OVER 
operator on the mainsurface, but maybe there is a better way?

here are some small code snippets:
//rectangle solution
  /* draws icon */
  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
  cairo_set_source_surface (cairo_context, object->background_surface, offset, 
offset);
  cairo_paint_with_alpha (cairo_context, launcher_icon->blend_alpha);

  /* draw prelight */
  if (object->prelight || !launcher_icon->running)
  {
    cairo_save (cairo_context);
      cairo_set_operator (cairo_context, CAIRO_OPERATOR_ATOP);
      cairo_rectangle (cairo_context, 0, 0, object->width, object->height);
      convert_color (dgconf->prelight_color, &r, &g, &b);
      cairo_set_source_rgba (cairo_context, r, g, b, dgconf->prelight_alpha);
      cairo_fill (cairo_context);
    cairo_restore (cairo_context);
  }

//workaround with surface for every icon (seems to work, but its causing heavy 
cpu load)
  /* create surface */
  surface = cairo_surface_create_similar (cairo_get_target (cairo_context), 
CAIRO_CONTENT_COLOR_ALPHA, object->width, object->height);

  cr = cairo_create (surface);
  cairo_set_source_rgba (cr, 1.0f, 1.0f, 1.0f, 0.0f);
  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
  cairo_paint (cr);

  /* draw icon on new surface */
  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
  cairo_set_source_surface (cr, object->background_surface, offset, offset);
  cairo_paint_with_alpha (cr, launcher_icon->blend_alpha);

  /* draw prelight on new surface */
  if (object->prelight || !launcher_icon->running)
  {
    cairo_save (cr);
      cairo_set_operator (cr, CAIRO_OPERATOR_ATOP);
      convert_color (dgconf->prelight_color, &r, &g, &b);
      cairo_set_source_rgba (cr, r, g, b, dgconf->prelight_alpha);
      cairo_paint (cr);
    cairo_restore (cr);
  }
  cairo_destroy (cr);

  /* draw new surface on main context */
  cairo_set_source_surface (cairo_context, surface, .0, .0);
  cairo_paint (cairo_context);
  cairo_surface_destroy (surface);

regards
danielb


More information about the cairo mailing list