Mercurial > hg > forks > geeqie
changeset 2081:2d6efc3deb26
added overlay and stereo input
author | Vladimir Nadvornik <nadvornik@suse.cz> |
---|---|
date | Wed, 15 Aug 2012 21:30:56 +0200 |
parents | b916ab9a2e4d |
children | a1fb3d7ce2ee |
files | src/renderer-clutter.c |
diffstat | 1 files changed, 192 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/src/renderer-clutter.c Tue Aug 14 23:55:16 2012 +0200 +++ b/src/renderer-clutter.c Wed Aug 15 21:30:56 2012 +0200 @@ -53,6 +53,16 @@ } ExifOrientationType; #endif +#define GET_RIGHT_PIXBUF_OFFSET(rc) \ + (( (rc->stereo_mode & PR_STEREO_RIGHT) && !(rc->stereo_mode & PR_STEREO_SWAP)) || \ + (!(rc->stereo_mode & PR_STEREO_RIGHT) && (rc->stereo_mode & PR_STEREO_SWAP)) ? \ + rc->pr->stereo_pixbuf_offset_right : rc->pr->stereo_pixbuf_offset_left ) + +#define GET_LEFT_PIXBUF_OFFSET(rc) \ + ((!(rc->stereo_mode & PR_STEREO_RIGHT) && !(rc->stereo_mode & PR_STEREO_SWAP)) || \ + ( (rc->stereo_mode & PR_STEREO_RIGHT) && (rc->stereo_mode & PR_STEREO_SWAP)) ? \ + rc->pr->stereo_pixbuf_offset_right : rc->pr->stereo_pixbuf_offset_left ) + typedef struct _OverlayData OverlayData; struct _OverlayData @@ -60,7 +70,7 @@ gint id; GdkPixbuf *pixbuf; - GdkWindow *window; + ClutterActor *actor; gint x; gint y; @@ -84,6 +94,8 @@ GList *pending_updates; gint idle_update; + GList *overlay_list; + GtkWidget *widget; /* widget and stage may be shared with other renderers */ ClutterActor *stage; ClutterActor *texture; @@ -238,7 +250,7 @@ CoglHandle texture = clutter_texture_get_cogl_texture(CLUTTER_TEXTURE(rc->texture)); cogl_texture_set_region(texture, - par->x, + par->x + GET_RIGHT_PIXBUF_OFFSET(rc), par->y, par->x, par->y, @@ -273,10 +285,23 @@ { RendererClutter *rc = (RendererClutter *)renderer; PixbufRenderer *pr = rc->pr; + RendererClutterAreaParam *par; + + gint width = gdk_pixbuf_get_width(pr->pixbuf); + gint height = gdk_pixbuf_get_height(pr->pixbuf); + + if (pr->stereo_data == STEREO_PIXBUF_SBS || pr->stereo_data == STEREO_PIXBUF_CROSS) + { + width /= 2; + } - RendererClutterAreaParam *par = g_new0(RendererClutterAreaParam, 1); + if (!pr_clip_region(src_x, src_y, src_w, src_h, + GET_RIGHT_PIXBUF_OFFSET(rc), 0, width, height, + &src_x, &src_y, &src_w, &src_h)) return; + + par = g_new0(RendererClutterAreaParam, 1); par->rc = rc; - par->x = src_x; + par->x = src_x - GET_RIGHT_PIXBUF_OFFSET(rc); par->y = src_y; par->w = src_w; par->h = src_h; @@ -313,6 +338,12 @@ gint prev_width, prev_height; + if (pr->stereo_data == STEREO_PIXBUF_SBS || pr->stereo_data == STEREO_PIXBUF_CROSS) + { + width /= 2; + } + + printf("renderer_update_pixbuf\n"); clutter_texture_get_base_size(CLUTTER_TEXTURE(rc->texture), &prev_width, &prev_height); printf("change from %d %d to %d %d\n", prev_width, prev_height, width, height); @@ -333,7 +364,7 @@ } if (!lazy) { - renderer_area_changed(renderer, 0, 0, width, height); + renderer_area_changed(renderer, GET_RIGHT_PIXBUF_OFFSET(rc), 0, width, height); } } @@ -357,22 +388,169 @@ { } +static OverlayData *rc_overlay_find(RendererClutter *rc, gint id) +{ + GList *work; + + work = rc->overlay_list; + while (work) + { + OverlayData *od = work->data; + work = work->next; + + if (od->id == id) return od; + } + + return NULL; +} + +static void rc_overlay_actor_destroy_cb(ClutterActor *actor, gpointer user_data) +{ + OverlayData *od = user_data; + od->actor = NULL; +} + +static void rc_overlay_free(RendererClutter *rc, OverlayData *od) +{ + rc->overlay_list = g_list_remove(rc->overlay_list, od); + + if (od->pixbuf) g_object_unref(G_OBJECT(od->pixbuf)); + if (od->actor) clutter_actor_destroy(od->actor); + g_free(od); +} + +static void rc_overlay_update_position(RendererClutter *rc, OverlayData *od) +{ + gint px, py, pw, ph; + + pw = gdk_pixbuf_get_width(od->pixbuf); + ph = gdk_pixbuf_get_height(od->pixbuf); + px = od->x; + py = od->y; + + if (od->flags & OVL_RELATIVE) + { + if (px < 0) px = rc->pr->viewport_width - pw + px; + if (py < 0) py = rc->pr->viewport_height - ph + py; + } + if (od->actor) clutter_actor_set_position(od->actor, px, py); +} + +static void rc_overlay_update_positions(RendererClutter *rc) +{ + GList *work; + + work = rc->overlay_list; + while (work) + { + OverlayData *od = work->data; + work = work->next; + + rc_overlay_update_position(rc, od); + } +} + +static void rc_overlay_free_all(RendererClutter *rc) +{ + GList *work; + + work = rc->overlay_list; + while (work) + { + OverlayData *od = work->data; + work = work->next; + + rc_overlay_free(rc, od); + } +} + + static void renderer_overlay_draw(void *renderer, gint x, gint y, gint w, gint h) { } -static void renderer_overlay_add(void *renderer, gint x, gint y, gint w, gint h) +static gint renderer_overlay_add(void *renderer, GdkPixbuf *pixbuf, gint x, gint y, OverlayRendererFlags flags) { + RendererClutter *rc = (RendererClutter *)renderer; + PixbufRenderer *pr = rc->pr; + OverlayData *od; + gint id; + + g_return_val_if_fail(IS_PIXBUF_RENDERER(pr), -1); + g_return_val_if_fail(pixbuf != NULL, -1); + + id = 1; + while (rc_overlay_find(rc, id)) id++; + + od = g_new0(OverlayData, 1); + od->id = id; + od->pixbuf = pixbuf; + g_object_ref(G_OBJECT(od->pixbuf)); + od->x = x; + od->y = y; + od->flags = flags; + + od->actor = gtk_clutter_texture_new(); + g_signal_connect (od->actor, "destroy", G_CALLBACK(rc_overlay_actor_destroy_cb), od); + + gtk_clutter_texture_set_from_pixbuf(GTK_CLUTTER_TEXTURE (od->actor), pixbuf, NULL); + clutter_container_add_actor(CLUTTER_CONTAINER(rc->group), od->actor); + + rc->overlay_list = g_list_append(rc->overlay_list, od); + rc_overlay_update_position(rc, od); + + return od->id; } -static void renderer_overlay_set(void *renderer, gint x, gint y, gint w, gint h) +static void renderer_overlay_set(void *renderer, gint id, GdkPixbuf *pixbuf, gint x, gint y) { + RendererClutter *rc = (RendererClutter *)renderer; + PixbufRenderer *pr = rc->pr; + OverlayData *od; + + g_return_if_fail(IS_PIXBUF_RENDERER(pr)); + + od = rc_overlay_find(rc, id); + if (!od) return; + + if (pixbuf) + { + g_object_ref(G_OBJECT(pixbuf)); + g_object_unref(G_OBJECT(od->pixbuf)); + od->pixbuf = pixbuf; + + od->x = x; + od->y = y; + + if (od->actor) gtk_clutter_texture_set_from_pixbuf(GTK_CLUTTER_TEXTURE(od->actor), pixbuf, NULL); + rc_overlay_update_position(rc, od); + } + else + { + rc_overlay_free(rc, od); + } } -static void renderer_overlay_get(void *renderer, gint x, gint y, gint w, gint h) +static gboolean renderer_overlay_get(void *renderer, gint id, GdkPixbuf **pixbuf, gint *x, gint *y) { + RendererClutter *rc = (RendererClutter *)renderer; + + PixbufRenderer *pr = rc->pr; + OverlayData *od; + + g_return_val_if_fail(IS_PIXBUF_RENDERER(pr), FALSE); + + od = rc_overlay_find(rc, id); + if (!od) return FALSE; + + if (pixbuf) *pixbuf = od->pixbuf; + if (x) *x = od->x; + if (y) *y = od->y; + + return TRUE; } + static void renderer_update_sizes(void *renderer) { RendererClutter *rc = (RendererClutter *)renderer; @@ -426,6 +604,7 @@ 0, rc->pr->viewport_height / 2.0, 0); rc_sync_actor(rc); + rc_overlay_update_positions(rc); } static void renderer_scroll(void *renderer, gint x_off, gint y_off) @@ -447,9 +626,12 @@ static void renderer_free(void *renderer) { RendererClutter *rc = (RendererClutter *)renderer; + GtkWidget *widget = gtk_bin_get_child(GTK_BIN(rc->pr)); + renderer_remove_pending_updates(rc); + + rc_overlay_free_all(rc); - GtkWidget *widget = gtk_bin_get_child(GTK_BIN(rc->pr)); if (widget) { /* widget still exists */ @@ -523,7 +705,7 @@ clutter_container_add_actor(CLUTTER_CONTAINER(rc->stage), rc->group); clutter_actor_set_clip_to_allocation(CLUTTER_ACTOR(rc->group), TRUE); - rc->texture = gtk_clutter_texture_new (); + rc->texture = clutter_texture_new (); clutter_container_add_actor(CLUTTER_CONTAINER(rc->group), rc->texture); g_object_ref(G_OBJECT(rc->widget));