camera: use the Cairo API to draw the surface

This commit is contained in:
Pierre Pronchery 2024-08-08 17:57:42 +02:00
parent df22589e2b
commit 444664a2cc

View File

@ -122,7 +122,9 @@ struct _Camera
GtkWidget * widget; GtkWidget * widget;
GtkWidget * window; GtkWidget * window;
PangoFontDescription * bold; PangoFontDescription * bold;
#if !GTK_CHECK_VERSION(3, 0, 0) #if GTK_CHECK_VERSION(3, 0, 0)
cairo_surface_t * surface;
#else
GdkGC * gc; GdkGC * gc;
#endif #endif
#if GTK_CHECK_VERSION(2, 18, 0) #if GTK_CHECK_VERSION(2, 18, 0)
@ -185,14 +187,14 @@ static gboolean _camera_on_can_mmap(GIOChannel * channel,
GIOCondition condition, gpointer data); GIOCondition condition, gpointer data);
static gboolean _camera_on_can_read(GIOChannel * channel, static gboolean _camera_on_can_read(GIOChannel * channel,
GIOCondition condition, gpointer data); GIOCondition condition, gpointer data);
static gboolean _camera_on_drawing_area_configure(GtkWidget * widget,
GdkEventConfigure * event, gpointer data);
#if GTK_CHECK_VERSION(3, 0, 0) #if GTK_CHECK_VERSION(3, 0, 0)
static gboolean _camera_on_drawing_area_draw(GtkWidget * widget, cairo_t * cr, static gboolean _camera_on_drawing_area_draw(GtkWidget * widget, cairo_t * cr,
gpointer data); gpointer data);
static void _camera_on_drawing_area_size_allocate(GtkWidget * widget, static void _camera_on_drawing_area_size_allocate(GtkWidget * widget,
GdkRectangle * allocation, gpointer data); GdkRectangle * allocation, gpointer data);
#else #else
static gboolean _camera_on_drawing_area_configure(GtkWidget * widget,
GdkEventConfigure * event, gpointer data);
static gboolean _camera_on_drawing_area_expose(GtkWidget * widget, static gboolean _camera_on_drawing_area_expose(GtkWidget * widget,
GdkEventExpose * event, gpointer data); GdkEventExpose * event, gpointer data);
#endif #endif
@ -269,7 +271,9 @@ Camera * camera_new(GtkWidget * window, GtkAccelGroup * group,
camera->widget = NULL; camera->widget = NULL;
camera->window = window; camera->window = window;
camera->bold = NULL; camera->bold = NULL;
#if !GTK_CHECK_VERSION(3, 0, 0) #if GTK_CHECK_VERSION(3, 0, 0)
camera->surface = NULL;
#else
camera->gc = NULL; camera->gc = NULL;
#endif #endif
camera->pr_window = NULL; camera->pr_window = NULL;
@ -328,14 +332,14 @@ Camera * camera_new(GtkWidget * window, GtkAccelGroup * group,
#if !GTK_CHECK_VERSION(3, 0, 0) #if !GTK_CHECK_VERSION(3, 0, 0)
camera->pixmap = NULL; camera->pixmap = NULL;
#endif #endif
g_signal_connect(camera->area, "configure-event", G_CALLBACK(
_camera_on_drawing_area_configure), camera);
#if GTK_CHECK_VERSION(3, 0, 0) #if GTK_CHECK_VERSION(3, 0, 0)
g_signal_connect(camera->area, "draw", G_CALLBACK( g_signal_connect(camera->area, "draw", G_CALLBACK(
_camera_on_drawing_area_draw), camera); _camera_on_drawing_area_draw), camera);
g_signal_connect(camera->area, "size-allocate", G_CALLBACK( g_signal_connect(camera->area, "size-allocate", G_CALLBACK(
_camera_on_drawing_area_size_allocate), camera); _camera_on_drawing_area_size_allocate), camera);
#else #else
g_signal_connect(camera->area, "configure-event", G_CALLBACK(
_camera_on_drawing_area_configure), camera);
g_signal_connect(camera->area, "expose-event", G_CALLBACK( g_signal_connect(camera->area, "expose-event", G_CALLBACK(
_camera_on_drawing_area_expose), camera); _camera_on_drawing_area_expose), camera);
#endif #endif
@ -1171,7 +1175,11 @@ void camera_stop(Camera * camera)
if(camera->pixbuf != NULL) if(camera->pixbuf != NULL)
g_object_unref(camera->pixbuf); g_object_unref(camera->pixbuf);
camera->pixbuf = NULL; camera->pixbuf = NULL;
#if !GTK_CHECK_VERSION(3, 0, 0) #if GTK_CHECK_VERSION(3, 0, 0)
if(camera->surface != NULL)
cairo_surface_destroy(camera->surface);
camera->surface = NULL;
#else
if(camera->pixmap != NULL) if(camera->pixmap != NULL)
g_object_unref(camera->pixmap); g_object_unref(camera->pixmap);
camera->pixmap = NULL; camera->pixmap = NULL;
@ -1342,6 +1350,33 @@ static gboolean _camera_on_can_read(GIOChannel * channel,
#if GTK_CHECK_VERSION(3, 0, 0) #if GTK_CHECK_VERSION(3, 0, 0)
/* camera_on_drawing_area_configure */
static gboolean _camera_on_drawing_area_configure(GtkWidget * widget,
GdkEventConfigure * event, gpointer data)
{
Camera * camera = data;
GtkAllocation * allocation = &camera->area_allocation;
cairo_t * cr;
(void) event;
gtk_widget_get_allocation(widget, allocation);
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() %dx%d\n", __func__, allocation->width,
allocation->height);
#endif
if(camera->surface != NULL)
cairo_surface_destroy(camera->surface);
camera->surface = gdk_window_create_similar_surface(
gtk_widget_get_window(widget), CAIRO_CONTENT_COLOR,
allocation->width, allocation->height);
cr = cairo_create(camera->surface);
cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
cairo_paint(cr);
cairo_destroy(cr);
return TRUE;
}
/* camera_on_drawing_area_draw */ /* camera_on_drawing_area_draw */
static gboolean _camera_on_drawing_area_draw(GtkWidget * widget, cairo_t * cr, static gboolean _camera_on_drawing_area_draw(GtkWidget * widget, cairo_t * cr,
gpointer data) gpointer data)
@ -1350,14 +1385,11 @@ static gboolean _camera_on_drawing_area_draw(GtkWidget * widget, cairo_t * cr,
(void) widget; (void) widget;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "DEBUG: %s() %p\n", __func__, camera->pixbuf); fprintf(stderr, "DEBUG: %s()\n", __func__);
#endif #endif
if(camera->pixbuf != NULL) cairo_set_source_surface(cr, camera->surface, 0, 0);
{
gdk_cairo_set_source_pixbuf(cr, camera->pixbuf, 0, 0);
cairo_paint(cr); cairo_paint(cr);
} return FALSE;
return TRUE;
} }
@ -1684,9 +1716,10 @@ static void _refresh_vflip(Camera * camera, GdkPixbuf ** pixbuf);
static gboolean _camera_on_refresh(gpointer data) static gboolean _camera_on_refresh(gpointer data)
{ {
Camera * camera = data; Camera * camera = data;
#if !GTK_CHECK_VERSION(3, 0, 0) #if GTK_CHECK_VERSION(3, 0, 0)
GtkAllocation * allocation = &camera->area_allocation; cairo_t * cr;
#endif #endif
GtkAllocation * allocation = &camera->area_allocation;
int width = camera->format.fmt.pix.width; int width = camera->format.fmt.pix.width;
int height = camera->format.fmt.pix.height; int height = camera->format.fmt.pix.height;
@ -1695,22 +1728,34 @@ static gboolean _camera_on_refresh(gpointer data)
camera->format.fmt.pix.pixelformat); camera->format.fmt.pix.pixelformat);
#endif #endif
_refresh_convert(camera); _refresh_convert(camera);
#if !GTK_CHECK_VERSION(3, 0, 0)
if(camera->hflip == FALSE if(camera->hflip == FALSE
&& camera->vflip == FALSE && camera->vflip == FALSE
&& width == allocation->width && width == allocation->width
&& height == allocation->height && height == allocation->height
&& camera->overlays_cnt == 0) && camera->overlays_cnt == 0)
{
/* render directly */ /* render directly */
#if GTK_CHECK_VERSION(3, 0, 0)
cr = cairo_create(camera->surface);
if(camera->pixbuf != NULL)
g_object_unref(camera->pixbuf);
camera->pixbuf = gdk_pixbuf_new_from_data(camera->rgb_buffer,
GDK_COLORSPACE_RGB, FALSE, 8, width, height,
width * 3, NULL, NULL);
gdk_cairo_set_source_pixbuf(cr, camera->pixbuf, 0.0, 0.0);
cairo_paint(cr);
cairo_destroy(cr);
#else
gdk_draw_rgb_image(camera->pixmap, camera->gc, 0, 0, gdk_draw_rgb_image(camera->pixmap, camera->gc, 0, 0,
width, height, GDK_RGB_DITHER_NORMAL, width, height, GDK_RGB_DITHER_NORMAL,
camera->rgb_buffer, width * 3); camera->rgb_buffer, width * 3);
else
#endif #endif
}
else
{ {
/* render after scaling */
if(camera->pixbuf != NULL) if(camera->pixbuf != NULL)
g_object_unref(camera->pixbuf); g_object_unref(camera->pixbuf);
/* render after scaling */
camera->pixbuf = gdk_pixbuf_new_from_data(camera->rgb_buffer, camera->pixbuf = gdk_pixbuf_new_from_data(camera->rgb_buffer,
GDK_COLORSPACE_RGB, FALSE, 8, width, height, GDK_COLORSPACE_RGB, FALSE, 8, width, height,
width * 3, NULL, NULL); width * 3, NULL, NULL);
@ -1718,7 +1763,12 @@ static gboolean _camera_on_refresh(gpointer data)
_refresh_vflip(camera, &camera->pixbuf); _refresh_vflip(camera, &camera->pixbuf);
_refresh_scale(camera, &camera->pixbuf); _refresh_scale(camera, &camera->pixbuf);
_refresh_overlays(camera, camera->pixbuf); _refresh_overlays(camera, camera->pixbuf);
#if !GTK_CHECK_VERSION(3, 0, 0) #if GTK_CHECK_VERSION(3, 0, 0)
cr = cairo_create(camera->surface);
gdk_cairo_set_source_pixbuf(cr, camera->pixbuf, 0.0, 0.0);
cairo_paint(cr);
cairo_destroy(cr);
#else
gdk_pixbuf_render_to_drawable(camera->pixbuf, camera->pixmap, gdk_pixbuf_render_to_drawable(camera->pixbuf, camera->pixmap,
camera->gc, 0, 0, 0, 0, -1, -1, camera->gc, 0, 0, 0, 0, -1, -1,
GDK_RGB_DITHER_NORMAL, 0, 0); GDK_RGB_DITHER_NORMAL, 0, 0);