/*
- * Geeqie
- * (C) 2006 John Ellis
- * Copyright (C) 2008 - 2012 The Geeqie Team
+ * Copyright (C) 2006 John Ellis
+ * Copyright (C) 2008 - 2016 The Geeqie Team
*
* Author: John Ellis
*
- * This software is released under the GNU General Public License (GNU GPL).
- * Please read the included file COPYING for more information.
- * This software comes with no warranty of any kind, use at your own risk!
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
PROP_WINDOW_LIMIT,
PROP_WINDOW_LIMIT_VALUE,
PROP_AUTOFIT_LIMIT,
- PROP_AUTOFIT_LIMIT_VALUE
+ PROP_AUTOFIT_LIMIT_VALUE,
+ PROP_ENLARGEMENT_LIMIT_VALUE
};
typedef enum {
100,
G_PARAM_READABLE | G_PARAM_WRITABLE));
+ g_object_class_install_property(gobject_class,
+ PROP_ENLARGEMENT_LIMIT_VALUE,
+ g_param_spec_uint("enlargement_limit_value",
+ "Size increase limit of image when autofitting",
+ NULL,
+ 100,
+ 999,
+ 500,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
signals[SIGNAL_ZOOM] =
g_signal_new("zoom",
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE, 1,
GDK_TYPE_EVENT);
-
+
signals[SIGNAL_UPDATE_PIXEL] =
g_signal_new("update-pixel",
G_OBJECT_CLASS_TYPE(gobject_class),
#endif
}
return renderer_tiles_new(pr);
-}
+}
static void pixbuf_renderer_init(PixbufRenderer *pr)
pr->scroller_id = 0;
pr->scroller_overlay = -1;
-
+
pr->x_mouse = -1;
pr->y_mouse = -1;
pr->norm_center_x = 0.5;
pr->norm_center_y = 0.5;
-
+
pr->stereo_mode = PR_STEREO_NONE;
-
+
+ pr->color.red =0;
+ pr->color.green =0;
+ pr->color.blue =0;
+
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);
case PROP_AUTOFIT_LIMIT_VALUE:
pr->autofit_limit_size = g_value_get_uint(value);
break;
+ case PROP_ENLARGEMENT_LIMIT_VALUE:
+ pr->enlargement_limit_size = g_value_get_uint(value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
case PROP_AUTOFIT_LIMIT_VALUE:
g_value_set_uint(value, pr->autofit_limit_size);
break;
+ case PROP_ENLARGEMENT_LIMIT_VALUE:
+ g_value_set_uint(value, pr->enlargement_limit_size);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
g_return_if_fail(IS_PIXBUF_RENDERER(pr));
- widget = GTK_WIDGET(pr);
-
- if (color) {
- GdkColor *slot;
-
- style = gtk_style_copy(gtk_widget_get_style(widget));
- slot = &style->bg[GTK_STATE_NORMAL];
-
- slot->red = color->red;
- slot->green = color->green;
- slot->blue = color->blue;
+ if (color)
+ {
+ pr->color.red = color->red;
+ pr->color.green = color->green;
+ pr->color.blue = color->blue;
+ }
+ else
+ {
+ pr->color.red = 0;
+ pr->color.green = 0;
+ pr->color.blue = 0;
}
- else {
- style = gtk_style_copy(gtk_widget_get_default_style());
- }
-
- gtk_widget_set_style(widget, style);
- pr->renderer->update_sizes(pr->renderer);
- if (pr->renderer2) pr->renderer2->update_sizes(pr->renderer2);
+ pr->renderer->update_viewport(pr->renderer);
+ if (pr->renderer2) pr->renderer2->update_viewport(pr->renderer2);
}
/*
gdouble zoom)
{
g_return_if_fail(IS_PIXBUF_RENDERER(pr));
- g_return_if_fail(tile_width >= 32 && tile_width >= 32);
+ g_return_if_fail(tile_width >= 32 && tile_height >= 32);
g_return_if_fail(width >= 32 && height > 32);
g_return_if_fail(func_request != NULL);
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);
}
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;
}
}
}
-static void pr_drag_signal(PixbufRenderer *pr, GdkEventButton *bevent)
+static void pr_drag_signal(PixbufRenderer *pr, GdkEventMotion *event)
{
- g_signal_emit(pr, signals[SIGNAL_DRAG], 0, bevent);
+ g_signal_emit(pr, signals[SIGNAL_DRAG], 0, event);
}
static void pr_update_pixel_signal(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.
src_x = pr->x_scroll + pr->vis_width / 2;
pr->norm_center_x = (gdouble)src_x / pr->width;
}
-
+
if (pr->height > pr->viewport_height)
{
src_y = pr->y_scroll + pr->vis_height / 2;
}
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);
scale = scale * factor;
}
+ if (pr->zoom_expand)
+ {
+ gdouble factor = (gdouble)pr->enlargement_limit_size / 100;
+ if (scale > factor)
+ {
+ w = w * factor / scale;
+ h = h * factor / scale;
+ scale = factor;
+ }
+ }
+
if (w < 1) w = 1;
if (h < 1) h = 1;
}
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->update_zoom(pr->renderer, lazy);
- if (pr->renderer2) pr->renderer2->update_zoom(pr->renderer2, lazy);
-// if (!lazy) pr_redraw(pr, TRUE);
- }
- if (redrawn) *redrawn = (invalidate || invalid);
-
- pixbuf_renderer_sync_scroll_center(pr);
-
return TRUE;
}
{
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);
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)
{
}
if (force) clamp_flags |= PR_ZOOM_INVALIDATE;
- if (lazy) clamp_flags |= PR_ZOOM_LAZY;
- if (!pr_zoom_clamp(pr, zoom, clamp_flags, &redrawn)) return;
+ (void) pr_parent_window_resize(pr, pr->width, pr->height);
+ 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);
if (force && new)
{
pr_scroll_clamp(pr);
-#if 0
- if (lazy)
- {
- pr->renderer->queue_clear(pr->renderer);
- if (pr->renderer2) pr->renderer2->queue_clear(pr->renderer2);
- }
- else
- {
- pr_redraw(pr, redrawn);
- }
-#endif
pr->renderer->update_zoom(pr->renderer, lazy);
if (pr->renderer2) pr->renderer2->update_zoom(pr->renderer2, lazy);
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;
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)
pr->y_scroll += y;
pr_scroll_clamp(pr);
-
+
pixbuf_renderer_sync_scroll_center(pr);
-
+
if (pr->x_scroll == old_x && pr->y_scroll == old_y) return;
pr_scroll_notify_signal(pr);
x_off = pr->x_scroll - old_x;
y_off = pr->y_scroll - old_y;
-
+
pr->renderer->scroll(pr->renderer, x_off, y_off);
if (pr->renderer2) pr->renderer2->scroll(pr->renderer2, x_off, y_off);
}
*-------------------------------------------------------------------
*/
-static gboolean pr_mouse_motion_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
+static gboolean pr_mouse_motion_cb(GtkWidget *widget, GdkEventMotion *event, gpointer data)
{
PixbufRenderer *pr;
gint accel;
+#if GTK_CHECK_VERSION(3,0,0)
+ GdkDeviceManager *device_manager;
+ GdkDevice *device;
+#endif
/* This is a hack, but work far the best, at least for single pointer systems.
* See http://bugzilla.gnome.org/show_bug.cgi?id=587714 for more. */
gint x, y;
- gdk_window_get_pointer (bevent->window, &x, &y, NULL);
- bevent->x = x;
- bevent->y = y;
+#if GTK_CHECK_VERSION(3,0,0)
+ device_manager = gdk_display_get_device_manager(gdk_window_get_display(event->window));
+ device = gdk_device_manager_get_client_pointer(device_manager);
+ gdk_window_get_device_position(event->window, device, &x, &y, NULL);
+#else
+ gdk_window_get_pointer (event->window, &x, &y, NULL);
+#endif
+ event->x = x;
+ event->y = y;
pr = PIXBUF_RENDERER(widget);
if (pr->scroller_id)
{
- pr->scroller_xpos = bevent->x;
- pr->scroller_ypos = bevent->y;
+ pr->scroller_xpos = event->x;
+ pr->scroller_ypos = event->y;
}
-
- pr->x_mouse = bevent->x;
- pr->y_mouse = bevent->y;
+
+ pr->x_mouse = event->x;
+ pr->y_mouse = event->y;
pr_update_pixel_signal(pr);
-
+
if (!pr->in_drag || !gdk_pointer_is_grabbed()) return FALSE;
if (pr->drag_moved < PR_DRAG_SCROLL_THRESHHOLD)
widget_set_cursor(widget, GDK_FLEUR);
}
- if (bevent->state & GDK_CONTROL_MASK)
+ if (event->state & GDK_CONTROL_MASK)
{
accel = PR_PAN_SHIFT_MULTIPLIER;
}
}
/* do the scroll */
- pixbuf_renderer_scroll(pr, (pr->drag_last_x - bevent->x) * accel,
- (pr->drag_last_y - bevent->y) * accel);
+ pixbuf_renderer_scroll(pr, (pr->drag_last_x - event->x) * accel,
+ (pr->drag_last_y - event->y) * accel);
- pr_drag_signal(pr, bevent);
+ pr_drag_signal(pr, event);
- pr->drag_last_x = bevent->x;
- pr->drag_last_y = bevent->y;
+ pr->drag_last_x = event->x;
+ pr->drag_last_y = event->y;
/* This is recommended by the GTK+ documentation, but does not work properly.
* Use deprecated way until GTK+ gets a solution for correct motion hint handling:
* http://bugzilla.gnome.org/show_bug.cgi?id=587714
*/
- /* gdk_event_request_motions (bevent); */
+ /* gdk_event_request_motions (event); */
return FALSE;
}
}
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);
}
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);
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",
*/
#define COLOR_BYTES 3 /* rgb */
-static void pr_create_anaglyph_RC(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h)
+#define RC 0 /* Red-Cyan */
+#define GM 1 /* Green-Magenta */
+#define YB 2 /* Yellow-Blue */
+
+static void pr_create_anaglyph_color(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h, guint mode)
{
gint srs, drs;
guchar *s_pix, *d_pix;
dp = dpi + (i * drs);
for (j = 0; j < w; j++)
{
- *dp = *sp; /* copy red channel */
+ switch(mode)
+ {
+ case RC:
+ dp[0] = sp[0]; /* copy red channel */
+ break;
+ case GM:
+ dp[1] = sp[1];
+ break;
+ case YB:
+ dp[0] = sp[0];
+ dp[1] = sp[1];
+ break;
+ }
sp += COLOR_BYTES;
dp += COLOR_BYTES;
}
}
}
-static void pr_create_anaglyph_gray(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h)
+static void pr_create_anaglyph_gray(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h, guint mode)
{
gint srs, drs;
guchar *s_pix, *d_pix;
{
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;
+ switch(mode)
+ {
+ case RC:
+ dp[0] = g2; /* red channel from sp */
+ dp[1] = g1; /* green and blue from dp */
+ dp[2] = g1;
+ break;
+ case GM:
+ dp[0] = g1;
+ dp[1] = g2;
+ dp[2] = g1;
+ break;
+ case YB:
+ dp[0] = g2;
+ dp[1] = g2;
+ dp[2] = g1;
+ break;
+ }
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)
+static void pr_create_anaglyph_dubois(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h, guint mode)
{
gint srs, drs;
guchar *s_pix, *d_pix;
guchar *sp, *dp;
guchar *spi, *dpi;
gint i, j, k;
+ double pr_dubois_matrix[3][6];
+ const static double pr_dubois_matrix_RC[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}};
+ const static double pr_dubois_matrix_GM[3][6] = {
+ {-0.062, -0.158, -0.039, 0.529, 0.705, 0.024},
+ { 0.284, 0.668, 0.143, -0.016, -0.015, -0.065},
+ {-0.015, -0.027, 0.021, 0.009, 0.075, 0.937}};
+ const static double pr_dubois_matrix_YB[3][6] = {
+ { 1.000, -0.193, 0.282, -0.015, -0.116, -0.016},
+ {-0.024, 0.855, 0.064, 0.006, 0.058, -0.016},
+ {-0.036, -0.163, 0.021, 0.089, 0.174, 0.858}};
+
+ switch(mode)
+ {
+ case RC:
+ memcpy(pr_dubois_matrix, pr_dubois_matrix_RC, sizeof pr_dubois_matrix);
+ break;
+ case GM:
+ memcpy(pr_dubois_matrix, pr_dubois_matrix_GM, sizeof pr_dubois_matrix);
+ break;
+ case YB:
+ memcpy(pr_dubois_matrix, pr_dubois_matrix_YB, sizeof pr_dubois_matrix);
+ break;
+ }
srs = gdk_pixbuf_get_rowstride(right);
s_pix = gdk_pixbuf_get_pixels(right);
for (j = 0; j < w; j++)
{
double res[3];
- for (k = 0; k < 3; k++)
+ 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];
}
}
}
-
+
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);
+ pr_create_anaglyph_color(pixbuf, right, x, y, w, h, RC);
+ else if (mode & PR_STEREO_ANAGLYPH_GM)
+ pr_create_anaglyph_color(pixbuf, right, x, y, w, h, GM);
+ else if (mode & PR_STEREO_ANAGLYPH_YB)
+ pr_create_anaglyph_color(pixbuf, right, x, y, w, h, YB);
+ else if (mode & PR_STEREO_ANAGLYPH_GRAY_RC)
+ pr_create_anaglyph_gray(pixbuf, right, x, y, w, h, RC);
+ else if (mode & PR_STEREO_ANAGLYPH_GRAY_GM)
+ pr_create_anaglyph_gray(pixbuf, right, x, y, w, h, GM);
+ else if (mode & PR_STEREO_ANAGLYPH_GRAY_YB)
+ pr_create_anaglyph_gray(pixbuf, right, x, y, w, h, YB);
+ else if (mode & PR_STEREO_ANAGLYPH_DB_RC)
+ pr_create_anaglyph_dubois(pixbuf, right, x, y, w, h, RC);
+ else if (mode & PR_STEREO_ANAGLYPH_DB_GM)
+ pr_create_anaglyph_dubois(pixbuf, right, x, y, w, h, GM);
+ else if (mode & PR_STEREO_ANAGLYPH_DB_YB)
+ pr_create_anaglyph_dubois(pixbuf, right, x, y, w, h, YB);
}
/*
case EXIF_ORIENTATION_LEFT_BOTTOM:
pr->image_width = gdk_pixbuf_get_height(pr->pixbuf);
pr->image_height = gdk_pixbuf_get_width(pr->pixbuf);
- if (pr->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 (pr->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;
}
-
+
break;
default:
pr->image_width = gdk_pixbuf_get_width(pr->pixbuf);
pr->image_height = gdk_pixbuf_get_height(pr->pixbuf);
- if (pr->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 (pr->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;
if (!pr->pixbuf)
{
- GtkWidget *box;
-
/* no pixbuf so just clear the window */
pr->image_width = 0;
pr->image_height = 0;
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
- {
-#if !GTK_CHECK_VERSION(3,0,0)
- gdk_window_clear(gtk_widget_get_window(box));
-#endif
- 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)
+ if (pr->stereo_mode & PR_STEREO_TEMP_DISABLE)
{
gint disable = !pr->pixbuf || ! pr->stereo_data;
pr_stereo_temp_disable(pr, disable);
pr->orientation = orientation;
pr_pixbuf_size_sync(pr);
- if (0)
- {
- 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);
-
- pr->renderer->update_sizes(pr->renderer);
- if (pr->renderer2) pr->renderer2->update_sizes(pr->renderer2);
}
gint pixbuf_renderer_get_orientation(PixbufRenderer *pr)
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)
+ if (pr->stereo_mode & PR_STEREO_TEMP_DISABLE)
{
gint disable = !pr->pixbuf || ! pr->stereo_data;
pr_stereo_temp_disable(pr, disable);
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_copy(PixbufRenderer *pr, PixbufRenderer *source)
+{
+ GObject *object;
+ PixbufRendererScrollResetType scroll_reset;
+
+ g_return_if_fail(IS_PIXBUF_RENDERER(pr));
+ g_return_if_fail(IS_PIXBUF_RENDERER(source));
+
+ if (pr == source) return;
+
+ 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_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;
+
+ 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
+ {
+ pixbuf_renderer_set_pixbuf(pr, source->pixbuf, source->zoom);
+ }
+
+ pr->scroll_reset = scroll_reset;
}
void pixbuf_renderer_area_changed(PixbufRenderer *pr, gint x, gint y, gint w, gint h)
static void pr_stereo_set(PixbufRenderer *pr)
{
if (!pr->renderer) pr->renderer = pr_backend_renderer_new(pr);
-
+
pr->renderer->stereo_set(pr->renderer, pr->stereo_mode & ~PR_STEREO_MIRROR_RIGHT & ~PR_STEREO_FLIP_RIGHT);
-
+
if (pr->stereo_mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED))
{
if (!pr->renderer2) pr->renderer2 = pr_backend_renderer_new(pr);
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)
+
+ 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);
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,
+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;
gint p_alpha, prs;
guchar *p_pix, *pp;
gint map_x, map_y, map_w, map_h;
-
+ size_t xoff, yoff;
+
g_return_val_if_fail(IS_PIXBUF_RENDERER(pr), FALSE);
g_return_val_if_fail(r_mouse != NULL && g_mouse != NULL && b_mouse != NULL, FALSE);
*b_mouse = -1;
return FALSE;
}
-
+
if (!pb) return FALSE;
pr_tile_region_map_orientation(pr->orientation,
if (map_x < 0 || map_x > gdk_pixbuf_get_width(pr->pixbuf) - 1) return FALSE;
if (map_y < 0 || map_y > gdk_pixbuf_get_height(pr->pixbuf) - 1) return FALSE;
-
+
p_alpha = gdk_pixbuf_get_has_alpha(pb);
prs = gdk_pixbuf_get_rowstride(pb);
p_pix = gdk_pixbuf_get_pixels(pb);
- pp = p_pix + map_y * prs + (map_x * (p_alpha ? 4 : 3));
+ xoff = (size_t)map_x * (p_alpha ? 4 : 3);
+ yoff = (size_t)map_y * prs;
+ pp = p_pix + yoff + xoff;
*r_mouse = *pp;
pp++;
*g_mouse = *pp;
pp++;
*b_mouse = *pp;
-
+
return TRUE;
}
gboolean pixbuf_renderer_get_mouse_position(PixbufRenderer *pr, gint *x_pixel_return, gint *y_pixel_return)
{
gint x_pixel, y_pixel, x_pixel_clamped, y_pixel_clamped;
-
+
g_return_val_if_fail(IS_PIXBUF_RENDERER(pr), FALSE);
g_return_val_if_fail(x_pixel_return != NULL && y_pixel_return != NULL, FALSE);
*y_pixel_return = -1;
return FALSE;
}
-
+
x_pixel = floor((gdouble)(pr->x_mouse - pr->x_offset + pr->x_scroll) / pr->scale);
y_pixel = floor((gdouble)(pr->y_mouse - pr->y_offset + pr->y_scroll) / pr->scale / pr->aspect_ratio);
x_pixel_clamped = CLAMP(x_pixel, 0, pr->image_width - 1);
y_pixel_clamped = CLAMP(y_pixel, 0, pr->image_height - 1);
-
+
if(x_pixel != x_pixel_clamped || y_pixel != y_pixel_clamped)
{
/* mouse is not on pr */
*x_pixel_return = x_pixel;
*y_pixel_return = y_pixel;
-
+
return TRUE;
}
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;
//pr->width = width;
//pr->height = height;
+#endif
}
/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */