X-Git-Url: http://geeqie.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fpixbuf-renderer.c;h=688a480eadf3f991ab8facc8980f8d77b33ecbbc;hb=e436ea53511e1dadab981af18b237fee83fde39b;hp=fb249f4baa7e40376d1112d2f8a2e706c33a2a5c;hpb=623bc05945e68c9242a69290de12501435a1bc18;p=geeqie.git diff --git a/src/pixbuf-renderer.c b/src/pixbuf-renderer.c index fb249f4b..688a480e 100644 --- a/src/pixbuf-renderer.c +++ b/src/pixbuf-renderer.c @@ -1,7 +1,7 @@ /* * Geeqie * (C) 2006 John Ellis - * Copyright (C) 2008 - 2010 The Geeqie Team + * Copyright (C) 2008 - 2012 The Geeqie Team * * Author: John Ellis * @@ -18,13 +18,13 @@ #include "main.h" #include "pixbuf-renderer.h" #include "renderer-tiles.h" +#include "renderer-clutter.h" #include "intl.h" #include "layout.h" #include - /* comment this out if not using this from within Geeqie * defining GQ_BUILD does these things: * - Sets the shift-click scroller pixbuf to a nice icon instead of a black box @@ -86,7 +86,6 @@ enum { PROP_ZOOM_QUALITY, PROP_ZOOM_2PASS, PROP_ZOOM_EXPAND, - PROP_DITHER_QUALITY, PROP_SCROLL_RESET, PROP_DELAY_FLIP, PROP_LOADING, @@ -121,8 +120,6 @@ static void pixbuf_renderer_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void pixbuf_renderer_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); -static gboolean pixbuf_renderer_expose(GtkWidget *widget, GdkEventExpose *event); - static void pr_scroller_timer_set(PixbufRenderer *pr, gboolean start); @@ -133,7 +130,7 @@ static void pr_zoom_sync(PixbufRenderer *pr, gdouble zoom, static void pr_signals_connect(PixbufRenderer *pr); static void pr_size_cb(GtkWidget *widget, GtkAllocation *allocation, gpointer data); -static void pixbuf_renderer_paint(PixbufRenderer *pr, GdkRectangle *area); +static void pr_stereo_temp_disable(PixbufRenderer *pr, gboolean disable); /* @@ -172,7 +169,6 @@ GType pixbuf_renderer_get_type(void) static void pixbuf_renderer_class_init(PixbufRendererClass *class) { GObjectClass *gobject_class = G_OBJECT_CLASS(class); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(class); parent_class = g_type_class_peek_parent(class); @@ -181,8 +177,6 @@ static void pixbuf_renderer_class_init(PixbufRendererClass *class) gobject_class->finalize = pixbuf_renderer_finalize; - widget_class->expose_event = pixbuf_renderer_expose; - g_object_class_install_property(gobject_class, PROP_ZOOM_MIN, g_param_spec_double("zoom_min", @@ -228,17 +222,6 @@ static void pixbuf_renderer_class_init(PixbufRendererClass *class) NULL, FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE)); - - g_object_class_install_property(gobject_class, - PROP_DITHER_QUALITY, - g_param_spec_uint("dither_quality", - "Dither quality", - NULL, - GDK_RGB_DITHER_NONE, - GDK_RGB_DITHER_MAX, - GDK_RGB_DITHER_NORMAL, - G_PARAM_READABLE | G_PARAM_WRITABLE)); - g_object_class_install_property(gobject_class, PROP_SCROLL_RESET, g_param_spec_uint("scroll_reset", @@ -396,6 +379,20 @@ static void pixbuf_renderer_class_init(PixbufRendererClass *class) G_TYPE_NONE, 0); } +static RendererFuncs *pr_backend_renderer_new(PixbufRenderer *pr) +{ + if (options->image.use_clutter_renderer) + { +#ifdef HAVE_CLUTTER + return renderer_clutter_new(pr); +#else + DEBUG_0("Geeqie is built without clutter renderer support"); +#endif + } + return renderer_tiles_new(pr); +} + + static void pixbuf_renderer_init(PixbufRenderer *pr) { GtkWidget *box; @@ -411,8 +408,6 @@ static void pixbuf_renderer_init(PixbufRenderer *pr) pr->scale = 1.0; pr->aspect_ratio = 1.0; - pr->dither_quality = GDK_RGB_DITHER_NORMAL; - pr->scroll_reset = PR_SCROLL_RESET_TOPLEFT; pr->scroller_id = 0; @@ -431,11 +426,12 @@ static void pixbuf_renderer_init(PixbufRenderer *pr) pr->stereo_mode = PR_STEREO_NONE; - pr->renderer = (void *)renderer_tiles_new(pr); + pr->renderer = pr_backend_renderer_new(pr); pr->renderer2 = NULL; gtk_widget_set_double_buffered(box, FALSE); + gtk_widget_set_app_paintable(box, TRUE); g_signal_connect_after(G_OBJECT(box), "size_allocate", G_CALLBACK(pr_size_cb), pr); @@ -449,7 +445,7 @@ static void pixbuf_renderer_finalize(GObject *object) pr = PIXBUF_RENDERER(object); pr->renderer->free(pr->renderer); - if (pr->renderer2) pr->renderer->free(pr->renderer2); + if (pr->renderer2) pr->renderer2->free(pr->renderer2); if (pr->pixbuf) g_object_unref(pr->pixbuf); @@ -488,9 +484,6 @@ static void pixbuf_renderer_set_property(GObject *object, guint prop_id, case PROP_ZOOM_EXPAND: pr->zoom_expand = g_value_get_boolean(value); break; - case PROP_DITHER_QUALITY: - pr->dither_quality = g_value_get_uint(value); - break; case PROP_SCROLL_RESET: pr->scroll_reset = g_value_get_uint(value); break; @@ -554,9 +547,6 @@ static void pixbuf_renderer_get_property(GObject *object, guint prop_id, case PROP_ZOOM_EXPAND: g_value_set_boolean(value, pr->zoom_expand); break; - case PROP_DITHER_QUALITY: - g_value_set_uint(value, pr->dither_quality); - break; case PROP_SCROLL_RESET: g_value_set_uint(value, pr->scroll_reset); break; @@ -596,41 +586,6 @@ static void pixbuf_renderer_get_property(GObject *object, guint prop_id, } } -static gboolean pixbuf_renderer_expose(GtkWidget *widget, GdkEventExpose *event) -{ -#if GTK_CHECK_VERSION(2,20,0) - if (gtk_widget_is_drawable(widget)) -#else - if (GTK_WIDGET_DRAWABLE(widget)) -#endif - { -#if GTK_CHECK_VERSION(2,20,0) - if (gtk_widget_get_has_window(widget)) -#else - if (!GTK_WIDGET_NO_WINDOW(widget)) -#endif - { - if (event->window != widget->window) - { - GdkRectangle area; - - gdk_window_get_position(event->window, &area.x, &area.y); - - area.x += event->area.x; - area.y += event->area.y; - area.width = event->area.width; - area.height = event->area.height; - pixbuf_renderer_paint(PIXBUF_RENDERER(widget), &area); - } - else - { - pixbuf_renderer_paint(PIXBUF_RENDERER(widget), &event->area); - } - } - } - - return FALSE; -} /* *------------------------------------------------------------------- @@ -642,7 +597,7 @@ static void widget_set_cursor(GtkWidget *widget, gint icon) { GdkCursor *cursor; - if (!widget->window) return; + if (!gtk_widget_get_window(widget)) return; if (icon == -1) { @@ -653,7 +608,7 @@ static void widget_set_cursor(GtkWidget *widget, gint icon) cursor = gdk_cursor_new(icon); } - gdk_window_set_cursor(widget->window, cursor); + gdk_window_set_cursor(gtk_widget_get_window(widget), cursor); if (cursor) gdk_cursor_unref(cursor); } @@ -685,10 +640,10 @@ static gboolean pr_parent_window_sizable(PixbufRenderer *pr) if (!pr->parent_window) return FALSE; if (!pr->window_fit) return FALSE; - if (!GTK_WIDGET(pr)->window) return FALSE; + if (!gtk_widget_get_window(GTK_WIDGET(pr))) return FALSE; - if (!pr->parent_window->window) return FALSE; - state = gdk_window_get_state(pr->parent_window->window); + if (!gtk_widget_get_window(pr->parent_window)) return FALSE; + state = gdk_window_get_state(gtk_widget_get_window(pr->parent_window)); if (state & GDK_WINDOW_STATE_MAXIMIZED) return FALSE; return TRUE; @@ -699,6 +654,8 @@ static gboolean pr_parent_window_resize(PixbufRenderer *pr, gint w, gint h) GtkWidget *widget; GtkWidget *parent; gint ww, wh; + GtkAllocation widget_allocation; + GtkAllocation parent_allocation; if (!pr_parent_window_sizable(pr)) return FALSE; @@ -714,13 +671,17 @@ static gboolean pr_parent_window_resize(PixbufRenderer *pr, gint w, gint h) widget = GTK_WIDGET(pr); parent = GTK_WIDGET(pr->parent_window); - w += (parent->allocation.width - widget->allocation.width); - h += (parent->allocation.height - widget->allocation.height); + gtk_widget_get_allocation(widget, &widget_allocation); + gtk_widget_get_allocation(parent, &parent_allocation); - gdk_drawable_get_size(parent->window, &ww, &wh); + w += (parent_allocation.width - widget_allocation.width); + h += (parent_allocation.height - widget_allocation.height); + + ww = gdk_window_get_width(gtk_widget_get_window(parent)); + wh = gdk_window_get_height(gtk_widget_get_window(parent)); if (w == ww && h == wh) return FALSE; - gdk_window_resize(parent->window, w, h); + gdk_window_resize(gtk_widget_get_window(parent), w, h); return TRUE; } @@ -927,12 +888,6 @@ static void pr_scroller_stop(PixbufRenderer *pr) *------------------------------------------------------------------- */ -static void pr_border_clear(PixbufRenderer *pr) -{ - pr->renderer->border_draw(pr->renderer, 0, 0, pr->viewport_width, pr->viewport_height); - if (pr->renderer2) pr->renderer2->border_draw(pr->renderer2, 0, 0, pr->viewport_width, pr->viewport_height); -} - void pixbuf_renderer_set_color(PixbufRenderer *pr, GdkColor *color) { GtkStyle *style; @@ -958,21 +913,8 @@ void pixbuf_renderer_set_color(PixbufRenderer *pr, GdkColor *color) gtk_widget_set_style(widget, style); -#if GTK_CHECK_VERSION(2,20,0) - if (gtk_widget_get_visible(widget)) pr_border_clear(pr); -#else - if (GTK_WIDGET_VISIBLE(widget)) pr_border_clear(pr); -#endif -} - -static void pr_redraw(PixbufRenderer *pr, gboolean new_data) -{ - pr->renderer->queue_clear(pr->renderer); - pr->renderer->queue(pr->renderer, 0, 0, pr->width, pr->height, TRUE, TILE_RENDER_ALL, new_data, FALSE); - if (pr->renderer2) { - pr->renderer2->queue_clear(pr->renderer2); - pr->renderer2->queue(pr->renderer2, 0, 0, pr->width, pr->height, TRUE, TILE_RENDER_ALL, new_data, FALSE); - } + pr->renderer->update_viewport(pr->renderer); + if (pr->renderer2) pr->renderer2->update_viewport(pr->renderer2); } /* @@ -1241,8 +1183,8 @@ void pixbuf_renderer_set_tiles(PixbufRenderer *pr, gint width, gint height, pr->func_tile_dispose = func_dispose; pr->func_tile_data = user_data; + pr_stereo_temp_disable(pr, TRUE); pr_zoom_sync(pr, zoom, PR_ZOOM_FORCE | PR_ZOOM_NEW, 0, 0); - pr_redraw(pr, TRUE); } void pixbuf_renderer_set_tiles_size(PixbufRenderer *pr, gint width, gint height) @@ -1320,9 +1262,6 @@ static void pr_zoom_adjust_real(PixbufRenderer *pr, gdouble increment, static void pr_update_signal(PixbufRenderer *pr) { -#if 0 - log_printf("FIXME: send updated signal\n"); -#endif DEBUG_1("%s pixbuf renderer updated - started drawing %p, img: %dx%d", get_exec_time(), pr, pr->image_width, pr->image_height); pr->debug_updated = TRUE; } @@ -1556,7 +1495,7 @@ static void pixbuf_renderer_sync_scroll_center(PixbufRenderer *pr) gint src_x, src_y; if (!pr->width || !pr->height) return; - /* + /* * Update norm_center only if the image is bigger than the window. * With this condition the stored center survives also a temporary display * of the "broken image" icon. @@ -1650,15 +1589,12 @@ static gboolean pr_size_clamp(PixbufRenderer *pr) } static gboolean pr_zoom_clamp(PixbufRenderer *pr, gdouble zoom, - PrZoomFlags flags, gboolean *redrawn) + PrZoomFlags flags) { gint w, h; gdouble scale; - gboolean invalid; gboolean force = !!(flags & PR_ZOOM_FORCE); gboolean new = !!(flags & PR_ZOOM_NEW); - gboolean invalidate = !!(flags & PR_ZOOM_INVALIDATE); - gboolean lazy = !!(flags & PR_ZOOM_LAZY); zoom = CLAMP(zoom, pr->zoom_min, pr->zoom_max); @@ -1742,23 +1678,11 @@ static gboolean pr_zoom_clamp(PixbufRenderer *pr, gdouble zoom, h = h * scale * pr->aspect_ratio; } - invalid = (pr->width != w || pr->height != h); - pr->zoom = zoom; pr->width = w; pr->height = h; pr->scale = scale; - if (invalidate || invalid) - { - pr->renderer->invalidate_all(pr->renderer); - if (pr->renderer2) pr->renderer2->invalidate_all(pr->renderer2); - if (!lazy) pr_redraw(pr, TRUE); - } - if (redrawn) *redrawn = (invalidate || invalid); - - pixbuf_renderer_sync_scroll_center(pr); - return TRUE; } @@ -1767,9 +1691,6 @@ static void pr_zoom_sync(PixbufRenderer *pr, gdouble zoom, { gdouble old_scale; gint old_cx, old_cy; - gboolean clamped; - gboolean sized; - gboolean redrawn = FALSE; gboolean center_point = !!(flags & PR_ZOOM_CENTER); gboolean force = !!(flags & PR_ZOOM_FORCE); gboolean new = !!(flags & PR_ZOOM_NEW); @@ -1777,7 +1698,7 @@ static void pr_zoom_sync(PixbufRenderer *pr, gdouble zoom, PrZoomFlags clamp_flags = flags; gdouble old_center_x = pr->norm_center_x; gdouble old_center_y = pr->norm_center_y; - + old_scale = pr->scale; if (center_point) { @@ -1794,11 +1715,10 @@ static void pr_zoom_sync(PixbufRenderer *pr, gdouble zoom, } if (force) clamp_flags |= PR_ZOOM_INVALIDATE; - if (lazy) clamp_flags |= PR_ZOOM_LAZY; - if (!pr_zoom_clamp(pr, zoom, clamp_flags, &redrawn)) return; + if (!pr_zoom_clamp(pr, zoom, clamp_flags)) return; - clamped = pr_size_clamp(pr); - sized = pr_parent_window_resize(pr, pr->width, pr->height); + (void) pr_size_clamp(pr); + (void) pr_parent_window_resize(pr, pr->width, pr->height); if (force && new) { @@ -1839,21 +1759,8 @@ static void pr_zoom_sync(PixbufRenderer *pr, gdouble zoom, pr_scroll_clamp(pr); - /* If the window was not sized, redraw the image - we know there will be no size/expose signal. - * But even if a size is claimed, there is no guarantee that the window manager will allow it, - * so redraw the window anyway :/ - */ - if (sized || clamped) pr_border_clear(pr); - - if (lazy) - { - pr->renderer->queue_clear(pr->renderer); - if (pr->renderer2) pr->renderer2->queue_clear(pr->renderer2); - } - else - { - pr_redraw(pr, redrawn); - } + pr->renderer->update_zoom(pr->renderer, lazy); + if (pr->renderer2) pr->renderer2->update_zoom(pr->renderer2, lazy); pr_scroll_notify_signal(pr); pr_zoom_signal(pr); @@ -1864,9 +1771,26 @@ static void pr_size_sync(PixbufRenderer *pr, gint new_width, gint new_height) { gboolean zoom_changed = FALSE; - gint new_viewport_width = (pr->stereo_mode & PR_STEREO_HORIZ) ? new_width / 2 : new_width; - gint new_viewport_height = (pr->stereo_mode & PR_STEREO_VERT) ? new_height / 2 : new_height; - + gint new_viewport_width = new_width; + gint new_viewport_height = new_height; + + if (!pr->stereo_temp_disable) + { + if (pr->stereo_mode & PR_STEREO_HORIZ) + { + new_viewport_width = new_width / 2; + } + else if (pr->stereo_mode & PR_STEREO_VERT) + { + new_viewport_height = new_height / 2; + } + else if (pr->stereo_mode & PR_STEREO_FIXED) + { + new_viewport_width = pr->stereo_fixed_width; + new_viewport_height = pr->stereo_fixed_height; + } + } + if (pr->window_width == new_width && pr->window_height == new_height && pr->viewport_width == new_viewport_width && pr->viewport_height == new_viewport_height) return; @@ -1878,15 +1802,22 @@ static void pr_size_sync(PixbufRenderer *pr, gint new_width, gint new_height) if (pr->zoom == 0.0) { gdouble old_scale = pr->scale; - pr_zoom_clamp(pr, 0.0, PR_ZOOM_FORCE, NULL); + pr_zoom_clamp(pr, 0.0, PR_ZOOM_FORCE); zoom_changed = (old_scale != pr->scale); } pr_size_clamp(pr); pr_scroll_clamp(pr); - pr->renderer->update_sizes(pr->renderer); - if (pr->renderer2) pr->renderer2->update_sizes(pr->renderer2); + if (zoom_changed) + { + pr->renderer->update_zoom(pr->renderer, FALSE); + if (pr->renderer2) pr->renderer2->update_zoom(pr->renderer2, FALSE); + } + + pr->renderer->update_viewport(pr->renderer); + if (pr->renderer2) pr->renderer2->update_viewport(pr->renderer2); + /* ensure scroller remains visible */ if (pr->scroller_overlay != -1) @@ -1922,8 +1853,6 @@ static void pr_size_sync(PixbufRenderer *pr, gint new_width, gint new_height) } } - pr_border_clear(pr); - pr_scroll_notify_signal(pr); if (zoom_changed) pr_zoom_signal(pr); pr_update_signal(pr); @@ -1936,31 +1865,6 @@ static void pr_size_cb(GtkWidget *widget, GtkAllocation *allocation, gpointer da pr_size_sync(pr, allocation->width, allocation->height); } -static void pixbuf_renderer_paint(PixbufRenderer *pr, GdkRectangle *area) -{ - gint x, y; - - - x = MAX(0, (gint)area->x - pr->x_offset + pr->x_scroll); - y = MAX(0, (gint)area->y - pr->y_offset + pr->y_scroll); - - pr->renderer->border_draw(pr->renderer, area->x, area->y, area->width, area->height); - pr->renderer->queue(pr->renderer, - x, y, - MIN((gint)area->width, pr->width - x), - MIN((gint)area->height, pr->height - y), - FALSE, TILE_RENDER_ALL, FALSE, FALSE); - if (pr->renderer2) - { - pr->renderer2->border_draw(pr->renderer2, area->x, area->y, area->width, area->height); - pr->renderer2->queue(pr->renderer2, - x, y, - MIN((gint)area->width, pr->width - x), - MIN((gint)area->height, pr->height - y), - FALSE, TILE_RENDER_ALL, FALSE, FALSE); - } -} - /* *------------------------------------------------------------------- * scrolling @@ -2131,7 +2035,7 @@ static gboolean pr_mouse_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpo pr->drag_last_x = bevent->x; pr->drag_last_y = bevent->y; pr->drag_moved = 0; - gdk_pointer_grab(widget->window, FALSE, + gdk_pointer_grab(gtk_widget_get_window(widget), FALSE, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_RELEASE_MASK, NULL, NULL, bevent->time); gtk_grab_add(widget); @@ -2147,11 +2051,7 @@ static gboolean pr_mouse_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpo } parent = gtk_widget_get_parent(widget); -#if GTK_CHECK_VERSION(2,20,0) if (widget && gtk_widget_get_can_focus(parent)) -#else - if (widget && GTK_WIDGET_CAN_FOCUS(parent)) -#endif { gtk_widget_grab_focus(parent); } @@ -2171,11 +2071,7 @@ static gboolean pr_mouse_release_cb(GtkWidget *widget, GdkEventButton *bevent, g return TRUE; } -#if GTK_CHECK_VERSION(2,20,0) if (gdk_pointer_is_grabbed() && gtk_widget_has_grab(GTK_WIDGET(pr))) -#else - if (gdk_pointer_is_grabbed() && GTK_WIDGET_HAS_GRAB(pr)) -#endif { gtk_grab_remove(widget); gdk_pointer_ungrab(bevent->time); @@ -2239,7 +2135,7 @@ static void pr_signals_connect(PixbufRenderer *pr) G_CALLBACK(pr_leave_notify_cb), pr); gtk_widget_set_events(GTK_WIDGET(pr), GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_SCROLL_MASK | GDK_LEAVE_NOTIFY_MASK); g_signal_connect(G_OBJECT(pr), "drag_begin", @@ -2254,7 +2150,7 @@ static void pr_signals_connect(PixbufRenderer *pr) */ #define COLOR_BYTES 3 /* rgb */ -void pr_create_anaglyph(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h) +static void pr_create_anaglyph_RC(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h) { gint srs, drs; guchar *s_pix, *d_pix; @@ -2282,8 +2178,95 @@ void pr_create_anaglyph(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gin } } } + +static void pr_create_anaglyph_gray(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h) +{ + gint srs, drs; + guchar *s_pix, *d_pix; + guchar *sp, *dp; + guchar *spi, *dpi; + gint i, j; + const double gc[3] = {0.299, 0.587, 0.114}; + + srs = gdk_pixbuf_get_rowstride(right); + s_pix = gdk_pixbuf_get_pixels(right); + spi = s_pix + (x * COLOR_BYTES); + + drs = gdk_pixbuf_get_rowstride(pixbuf); + d_pix = gdk_pixbuf_get_pixels(pixbuf); + dpi = d_pix + x * COLOR_BYTES; + + for (i = y; i < y + h; i++) + { + sp = spi + (i * srs); + dp = dpi + (i * drs); + for (j = 0; j < w; j++) + { + guchar g1 = dp[0] * gc[0] + dp[1] * gc[1] + dp[2] * gc[2]; + guchar g2 = sp[0] * gc[0] + sp[1] * gc[1] + sp[2] * gc[2]; + dp[0] = g2; /* red channel from sp */ + dp[1] = g1; /* green and blue from dp */ + dp[2] = g1; + sp += COLOR_BYTES; + dp += COLOR_BYTES; + } + } +} + +const double pr_dubois_matrix[3][6] = { + { 0.456, 0.500, 0.176, -0.043, -0.088, -0.002}, + {-0.040, -0.038, -0.016, 0.378, 0.734, -0.018}, + {-0.015, -0.021, -0.005, -0.072, -0.113, 1.226} + }; + +static void pr_create_anaglyph_dubois(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h) +{ + gint srs, drs; + guchar *s_pix, *d_pix; + guchar *sp, *dp; + guchar *spi, *dpi; + gint i, j, k; + + srs = gdk_pixbuf_get_rowstride(right); + s_pix = gdk_pixbuf_get_pixels(right); + spi = s_pix + (x * COLOR_BYTES); + + drs = gdk_pixbuf_get_rowstride(pixbuf); + d_pix = gdk_pixbuf_get_pixels(pixbuf); + dpi = d_pix + x * COLOR_BYTES; + + for (i = y; i < y + h; i++) + { + sp = spi + (i * srs); + dp = dpi + (i * drs); + for (j = 0; j < w; j++) + { + double res[3]; + for (k = 0; k < 3; k++) + { + const double *m = pr_dubois_matrix[k]; + res[k] = sp[0] * m[0] + sp[1] * m[1] + sp[2] * m[2] + dp[0] * m[3] + dp[1] * m[4] + dp[2] * m[5]; + if (res[k] < 0.0) res[k] = 0; + if (res[k] > 255.0) res[k] = 255.0; + } + dp[0] = res[0]; + dp[1] = res[1]; + dp[2] = res[2]; + sp += COLOR_BYTES; + dp += COLOR_BYTES; + } + } +} - +void pr_create_anaglyph(guint mode, GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h) +{ + if (mode & PR_STEREO_ANAGLYPH_RC) + pr_create_anaglyph_RC(pixbuf, right, x, y, w, h); + else if (mode & PR_STEREO_ANAGLYPH_GRAY) + pr_create_anaglyph_gray(pixbuf, right, x, y, w, h); + else if (mode & PR_STEREO_ANAGLYPH_DB) + pr_create_anaglyph_dubois(pixbuf, right, x, y, w, h); +} /* *------------------------------------------------------------------- @@ -2295,7 +2278,6 @@ static void pr_pixbuf_size_sync(PixbufRenderer *pr) pr->stereo_pixbuf_offset_left = 0; pr->stereo_pixbuf_offset_right = 0; if (!pr->pixbuf) return; - gint stereo_data = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(pr->pixbuf), "stereo_data")); switch (pr->orientation) { case EXIF_ORIENTATION_LEFT_TOP: @@ -2304,12 +2286,12 @@ static void pr_pixbuf_size_sync(PixbufRenderer *pr) case EXIF_ORIENTATION_LEFT_BOTTOM: pr->image_width = gdk_pixbuf_get_height(pr->pixbuf); pr->image_height = gdk_pixbuf_get_width(pr->pixbuf); - if (stereo_data == STEREO_PIXBUF_SBS) + if (pr->stereo_data == STEREO_PIXBUF_SBS) { pr->image_height /= 2; pr->stereo_pixbuf_offset_right = pr->image_height; } - else if (stereo_data == STEREO_PIXBUF_CROSS) + else if (pr->stereo_data == STEREO_PIXBUF_CROSS) { pr->image_height /= 2; pr->stereo_pixbuf_offset_left = pr->image_height; @@ -2319,12 +2301,12 @@ static void pr_pixbuf_size_sync(PixbufRenderer *pr) default: pr->image_width = gdk_pixbuf_get_width(pr->pixbuf); pr->image_height = gdk_pixbuf_get_height(pr->pixbuf); - if (stereo_data == STEREO_PIXBUF_SBS) + if (pr->stereo_data == STEREO_PIXBUF_SBS) { pr->image_width /= 2; pr->stereo_pixbuf_offset_right = pr->image_width; } - else if (stereo_data == STEREO_PIXBUF_CROSS) + else if (pr->stereo_data == STEREO_PIXBUF_CROSS) { pr->image_width /= 2; pr->stereo_pixbuf_offset_left = pr->image_width; @@ -2340,8 +2322,6 @@ static void pr_set_pixbuf(PixbufRenderer *pr, GdkPixbuf *pixbuf, gdouble zoom, P if (!pr->pixbuf) { - GtkWidget *box; - /* no pixbuf so just clear the window */ pr->image_width = 0; pr->image_height = 0; @@ -2349,25 +2329,23 @@ static void pr_set_pixbuf(PixbufRenderer *pr, GdkPixbuf *pixbuf, gdouble zoom, P pr->zoom = zoom; /* don't throw away the zoom value, it is set by pixbuf_renderer_move, among others, and used for pixbuf_renderer_zoom_get */ - box = GTK_WIDGET(pr); - -#if GTK_CHECK_VERSION(2,20,0) - if (gtk_widget_get_realized(box)) -#else - if (GTK_WIDGET_REALIZED(box)) -#endif - { - gdk_window_clear(box->window); - pr->renderer->overlay_draw(pr->renderer, 0, 0, pr->viewport_width, pr->viewport_height); - if (pr->renderer2) pr->renderer2->overlay_draw(pr->renderer2, 0, 0, pr->viewport_width, pr->viewport_height); - } + pr->renderer->update_pixbuf(pr->renderer, flags & PR_ZOOM_LAZY); + if (pr->renderer2) pr->renderer2->update_pixbuf(pr->renderer2, flags & PR_ZOOM_LAZY); pr_update_signal(pr); return; } + if (pr->stereo_mode & PR_STEREO_TEMP_DISABLE) + { + gint disable = !pr->pixbuf || ! pr->stereo_data; + pr_stereo_temp_disable(pr, disable); + } + pr_pixbuf_size_sync(pr); + pr->renderer->update_pixbuf(pr->renderer, flags & PR_ZOOM_LAZY); + if (pr->renderer2) pr->renderer2->update_pixbuf(pr->renderer2, flags & PR_ZOOM_LAZY); pr_zoom_sync(pr, zoom, flags | PR_ZOOM_FORCE | PR_ZOOM_NEW, 0, 0); } @@ -2382,13 +2360,14 @@ void pixbuf_renderer_set_pixbuf(PixbufRenderer *pr, GdkPixbuf *pixbuf, gdouble z pr_update_signal(pr); } -void pixbuf_renderer_set_pixbuf_lazy(PixbufRenderer *pr, GdkPixbuf *pixbuf, gdouble zoom, gint orientation) +void pixbuf_renderer_set_pixbuf_lazy(PixbufRenderer *pr, GdkPixbuf *pixbuf, gdouble zoom, gint orientation, StereoPixbufData stereo_data) { g_return_if_fail(IS_PIXBUF_RENDERER(pr)); pr_source_tile_unset(pr); pr->orientation = orientation; + pr->stereo_data = stereo_data; pr_set_pixbuf(pr, pixbuf, zoom, PR_ZOOM_LAZY); pr_update_signal(pr); @@ -2417,6 +2396,25 @@ gint pixbuf_renderer_get_orientation(PixbufRenderer *pr) return pr->orientation; } +void pixbuf_renderer_set_stereo_data(PixbufRenderer *pr, StereoPixbufData stereo_data) +{ + g_return_if_fail(IS_PIXBUF_RENDERER(pr)); + if (pr->stereo_data == stereo_data) return; + + + pr->stereo_data = stereo_data; + + if (pr->stereo_mode & PR_STEREO_TEMP_DISABLE) + { + gint disable = !pr->pixbuf || ! pr->stereo_data; + pr_stereo_temp_disable(pr, disable); + } + pr_pixbuf_size_sync(pr); + pr->renderer->update_pixbuf(pr->renderer, FALSE); + if (pr->renderer2) pr->renderer2->update_pixbuf(pr->renderer2, FALSE); + pr_zoom_sync(pr, pr->zoom, PR_ZOOM_FORCE, 0, 0); +} + void pixbuf_renderer_set_post_process_func(PixbufRenderer *pr, PixbufRendererPostProcessFunc func, gpointer user_data, gboolean slow) { g_return_if_fail(IS_PIXBUF_RENDERER(pr)); @@ -2458,6 +2456,7 @@ void pixbuf_renderer_move(PixbufRenderer *pr, PixbufRenderer *source) pr->post_process_user_data = source->post_process_user_data; pr->post_process_slow = source->post_process_slow; pr->orientation = source->orientation; + pr->stereo_data = source->stereo_data; if (source->source_tiles_enabled) { @@ -2478,7 +2477,6 @@ void pixbuf_renderer_move(PixbufRenderer *pr, PixbufRenderer *source) source->source_tiles = NULL; pr_zoom_sync(pr, source->zoom, PR_ZOOM_FORCE | PR_ZOOM_NEW, 0, 0); - pr_redraw(pr, TRUE); } else { @@ -2488,42 +2486,74 @@ void pixbuf_renderer_move(PixbufRenderer *pr, PixbufRenderer *source) pr->scroll_reset = scroll_reset; pixbuf_renderer_set_pixbuf(source, NULL, source->zoom); -// pr_queue_clear(source); -// pr_tile_free_all(source); } -void pixbuf_renderer_area_changed(PixbufRenderer *pr, gint src_x, gint src_y, gint src_w, gint src_h) +void pixbuf_renderer_copy(PixbufRenderer *pr, PixbufRenderer *source) { - gint x, y, width, height, x1, y1, x2, y2; + GObject *object; + PixbufRendererScrollResetType scroll_reset; g_return_if_fail(IS_PIXBUF_RENDERER(pr)); + g_return_if_fail(IS_PIXBUF_RENDERER(source)); - pr_coords_map_orientation_reverse(pr->orientation, - src_x, src_y, - pr->image_width, pr->image_height, - src_w, src_h, - &x, &y, - &width, &height); + if (pr == source) return; - if (pr->source_tiles_enabled) + object = G_OBJECT(pr); + + g_object_set(object, "zoom_min", source->zoom_min, NULL); + g_object_set(object, "zoom_max", source->zoom_max, NULL); + g_object_set(object, "loading", source->loading, NULL); + + pr->complete = source->complete; + + pr->x_scroll = source->x_scroll; + pr->y_scroll = source->y_scroll; + pr->x_mouse = source->x_mouse; + pr->y_mouse = source->y_mouse; + + scroll_reset = pr->scroll_reset; + pr->scroll_reset = PR_SCROLL_RESET_NOCHANGE; + + pr->orientation = source->orientation; + pr->stereo_data = source->stereo_data; + + if (source->source_tiles_enabled) { - pr_source_tile_changed(pr, x, y, width, height); - } + pr->source_tiles_enabled = source->source_tiles_enabled; + pr->source_tiles_cache_size = source->source_tiles_cache_size; + pr->source_tile_width = source->source_tile_width; + pr->source_tile_height = source->source_tile_height; + pr->image_width = source->image_width; + pr->image_height = source->image_height; + + pr->func_tile_request = source->func_tile_request; + pr->func_tile_dispose = source->func_tile_dispose; + pr->func_tile_data = source->func_tile_data; - if (pr->scale != 1.0 && pr->zoom_quality != GDK_INTERP_NEAREST) + pr->source_tiles = source->source_tiles; + source->source_tiles = NULL; + + pr_zoom_sync(pr, source->zoom, PR_ZOOM_FORCE | PR_ZOOM_NEW, 0, 0); + } + else { - /* increase region when using a zoom quality that may access surrounding pixels */ - y -= 1; - height += 2; + pixbuf_renderer_set_pixbuf(pr, source->pixbuf, source->zoom); } - x1 = (gint)floor((gdouble)x * pr->scale); - y1 = (gint)floor((gdouble)y * pr->scale * pr->aspect_ratio); - x2 = (gint)ceil((gdouble)(x + width) * pr->scale); - y2 = (gint)ceil((gdouble)(y + height) * pr->scale * pr->aspect_ratio); + pr->scroll_reset = scroll_reset; +} + +void pixbuf_renderer_area_changed(PixbufRenderer *pr, gint x, gint y, gint w, gint h) +{ + g_return_if_fail(IS_PIXBUF_RENDERER(pr)); + + if (pr->source_tiles_enabled) + { + pr_source_tile_changed(pr, x, y, w, h); + } - pr->renderer->queue(pr->renderer, x1, y1, x2 - x1, y2 - y1, FALSE, TILE_RENDER_AREA, TRUE, TRUE); - if (pr->renderer2) pr->renderer2->queue(pr->renderer2, x1, y1, x2 - x1, y2 - y1, FALSE, TILE_RENDER_AREA, TRUE, TRUE); + pr->renderer->area_changed(pr->renderer, x, y, w, h); + if (pr->renderer2) pr->renderer2->area_changed(pr->renderer2, x, y, w, h); } void pixbuf_renderer_zoom_adjust(PixbufRenderer *pr, gdouble increment) @@ -2581,38 +2611,86 @@ void pixbuf_renderer_zoom_set_limits(PixbufRenderer *pr, gdouble min, gdouble ma } } -void pixbuf_renderer_stereo_set(PixbufRenderer *pr, gint stereo_mode) +static void pr_stereo_set(PixbufRenderer *pr) { - gboolean redraw = !(pr->stereo_mode == stereo_mode); - pr->stereo_mode = stereo_mode; + if (!pr->renderer) pr->renderer = pr_backend_renderer_new(pr); - if (!pr->renderer) pr->renderer = (void *)renderer_tiles_new(pr); + pr->renderer->stereo_set(pr->renderer, pr->stereo_mode & ~PR_STEREO_MIRROR_RIGHT & ~PR_STEREO_FLIP_RIGHT); - pr->renderer->stereo_set(pr->renderer, pr->stereo_mode); - - if (pr->stereo_mode & (PR_STEREO_HORIZ | PR_STEREO_VERT)) + if (pr->stereo_mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED)) { - if (!pr->renderer2) pr->renderer2 = (void *)renderer_tiles_new(pr); - pr->renderer2->stereo_set(pr->renderer2, pr->stereo_mode | PR_STEREO_RIGHT); + if (!pr->renderer2) pr->renderer2 = pr_backend_renderer_new(pr); + pr->renderer2->stereo_set(pr->renderer2, (pr->stereo_mode & ~PR_STEREO_MIRROR_LEFT & ~PR_STEREO_FLIP_LEFT) | PR_STEREO_RIGHT); } else { if (pr->renderer2) pr->renderer2->free(pr->renderer2); pr->renderer2 = NULL; } - if (redraw) + if (pr->stereo_mode & PR_STEREO_HALF) + { + if (pr->stereo_mode & PR_STEREO_HORIZ) pr->aspect_ratio = 2.0; + else if (pr->stereo_mode & PR_STEREO_VERT) pr->aspect_ratio = 0.5; + else pr->aspect_ratio = 1.0; + } + else + { + pr->aspect_ratio = 1.0; + } +} + +void pixbuf_renderer_stereo_set(PixbufRenderer *pr, gint stereo_mode) +{ + gboolean redraw = !(pr->stereo_mode == stereo_mode) || pr->stereo_temp_disable; + pr->stereo_mode = stereo_mode; + if ((stereo_mode & PR_STEREO_TEMP_DISABLE) && pr->stereo_temp_disable) return; + + pr->stereo_temp_disable = FALSE; + + pr_stereo_set(pr); + + if (redraw) { pr_size_sync(pr, pr->window_width, pr->window_height); /* recalculate new viewport */ pr_zoom_sync(pr, pr->zoom, PR_ZOOM_FORCE | PR_ZOOM_NEW, 0, 0); } } +void pixbuf_renderer_stereo_fixed_set(PixbufRenderer *pr, gint width, gint height, gint x1, gint y1, gint x2, gint y2) +{ + pr->stereo_fixed_width = width; + pr->stereo_fixed_height = height; + pr->stereo_fixed_x_left = x1; + pr->stereo_fixed_y_left = y1; + pr->stereo_fixed_x_right = x2; + pr->stereo_fixed_y_right = y2; +} + gint pixbuf_renderer_stereo_get(PixbufRenderer *pr) { return pr->stereo_mode; } -gboolean pixbuf_renderer_get_pixel_colors(PixbufRenderer *pr, gint x_pixel, gint y_pixel, +static void pr_stereo_temp_disable(PixbufRenderer *pr, gboolean disable) +{ + if (pr->stereo_temp_disable == disable) return; + pr->stereo_temp_disable = disable; + if (disable) + { + if (!pr->renderer) pr->renderer = pr_backend_renderer_new(pr); + pr->renderer->stereo_set(pr->renderer, PR_STEREO_NONE); + if (pr->renderer2) pr->renderer2->free(pr->renderer2); + pr->renderer2 = NULL; + pr->aspect_ratio = 1.0; + } + else + { + pr_stereo_set(pr); + } + pr_size_sync(pr, pr->window_width, pr->window_height); /* recalculate new viewport */ +} + +gboolean pixbuf_renderer_get_pixel_colors(PixbufRenderer *pr, gint x_pixel, gint y_pixel, gint *r_mouse, gint *g_mouse, gint *b_mouse) { GdkPixbuf *pb = pr->pixbuf; @@ -2767,6 +2845,9 @@ gboolean pixbuf_renderer_get_virtual_rect(PixbufRenderer *pr, GdkRectangle *rect void pixbuf_renderer_set_size_early(PixbufRenderer *pr, guint width, guint height) { +#if 0 + /* FIXME: this function does not consider the image orientation, + so it probably only breaks something */ gdouble zoom; gint w, h; @@ -2781,6 +2862,7 @@ void pixbuf_renderer_set_size_early(PixbufRenderer *pr, guint width, guint heigh //pr->width = width; //pr->height = height; +#endif } /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */