[cairo] drag selection box over image surface
Rick W. Chen
stuffcorpse at gmail.com
Fri Mar 7 21:30:28 PST 2008
Hello, I'm new here (and to cairo too). I'm trying to draw a selection
box while the mouse is click-dragged on an image surface. Hope I have
the right mailing list. If not let me know where I should bugger off to.
Right now the box is drawn, but if the mouse moves (still dragging)
back, all previous boxes which are not painted over (because the current
box is smaller) remains. I can queue_draw() after painting the box each
time. That gives the desired effect, but it becomes noticeably slower
because on expose event, the image gets scaled to fit the gtk widget.
Plus it makes flickers.
Not sure if I have got the idea right in what I'm trying to do. If
someone can help me with this problem I would really appreciate it.
Below are some code related to this. paint_selection draws the box, and
on_event overloads the one from the widget (a DrawingArea).
void ImageArea::paint_selection(Cairo::RefPtr<Cairo::Context> cr)
{
if (!active)
return;
cr->save();
cr->set_line_width(2);
cr->rectangle(x, y, w, h);
cr->set_source_rgba(1, 1, 0.74, 0.2);
cr->fill_preserve();
cr->set_source_rgba(1, 1, 0.74, 0.5);
cr->stroke();
cr->restore();
}
bool ImageArea::on_event(GdkEvent *event)
{
if (!loaded_)
return true;
GdkEventButton *bevent;
GdkEventMotion *mevent;
GdkEventExpose *xevent;
int width = get_allocation().get_width();
int height = get_allocation().get_height();
// Create the context for the widget
Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
switch((gint)event->type)
{
case Gdk::BUTTON_PRESS:
bevent = (GdkEventButton *) event;
if(!select.active)
{
select.active = TRUE;
select.x = bevent->x/scaled_res.x;
select.y = bevent->y/scaled_res.y;
select.w = 0;
select.h = 0;
queue_draw();
}
break;
case Gdk::BUTTON_RELEASE:
bevent = (GdkEventButton *) event;
select.active = FALSE;
queue_draw();
break;
case Gdk::MOTION_NOTIFY:
mevent = (GdkEventMotion *) event;
if(select.active)
{
select.w = mevent->x/scaled_res.x - select.x;
select.h = mevent->y/scaled_res.y - select.y;
cr->rectangle (0.0, 0.0, width, height);
cr->scale( scaled_res.x, scaled_res.y );
cr->clip();
cr->save();
cr->set_source (image_surface_ptr_, 0.0, 0.0);
cr->rectangle (select.x, select.y, select.w, select.h);
cr->clip();
cr->paint();
select.paint_selection(cr);
cr->restore();
}
break;
case Gdk::EXPOSE:
xevent = (GdkEventExpose *) event;
// Select the clipping rectangle
cr->rectangle(xevent->area.x, xevent->area.y,
xevent->area.width, xevent->area.height);
// Scale image to fit drawing surface
cr->scale( scaled_res.x, scaled_res.y );
cr->clip();
cr->save();
// Draw the source image on the widget context
cr->set_source (image_surface_ptr_, 0.0, 0.0);
cr->rectangle (0.0, 0.0, image.width, image.height);
cr->clip();
cr->paint();
cr->restore();
}
return true;
}
--
Rick
More information about the cairo
mailing list