2
* * Copyright (C) 2006-2011 Anders Brander <anders@brander.dk>,
3
* * Anders Kvist <akv@lnxbx.dk> and Klaus Post <klauspost@gmail.com>
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
#include <rawstudio.h>
23
G_DEFINE_TYPE (RSLoupe, rs_loupe, GTK_TYPE_WINDOW)
25
static gboolean expose(GtkWidget *widget, GdkEventExpose *event, RSLoupe *loupe);
26
static void move(RSLoupe *loupe);
27
static void redraw(RSLoupe *loupe);
30
rs_loupe_finalize(GObject *object)
32
RSLoupe *loupe = RS_LOUPE(object);
35
g_object_unref(loupe->filter);
37
G_OBJECT_CLASS (rs_loupe_parent_class)->finalize (object);
41
rs_loupe_class_init(RSLoupeClass *klass)
43
GObjectClass *object_class = G_OBJECT_CLASS (klass);
45
object_class->finalize = rs_loupe_finalize;
49
rs_loupe_init(RSLoupe *loupe)
52
GdkScreen *screen = gdk_screen_get_default();
53
const gint screen_width = gdk_screen_get_width(screen);
54
const gint screen_height = gdk_screen_get_height(screen);
56
const gint loupe_size = MIN(screen_width/4, screen_height/3);
58
/* Initialize window */
59
gtk_window_resize(GTK_WINDOW(loupe), loupe_size, loupe_size);
60
gtk_window_set_keep_above(GTK_WINDOW(loupe), TRUE);
62
/* We have to grab focus, otherwise window will not show up in fullscreen mode */
63
g_object_set(GTK_WINDOW(loupe),
67
"focus-on-map", FALSE,
68
"skip-pager-hint", TRUE,
69
"skip-taskbar-hint", TRUE,
72
loupe->canvas = gtk_drawing_area_new();
73
gtk_container_add(GTK_CONTAINER(loupe), loupe->canvas);
75
g_signal_connect(loupe->canvas, "expose-event", G_CALLBACK(expose), loupe);
79
* Instantiates a new RSLoupe
80
* @return A new RSLoupe
85
return g_object_new(RS_TYPE_LOUPE, "type", GTK_WINDOW_POPUP, NULL);
89
* Set the RSFilter a RSLoupe will get its image data from
90
* @param loupe A RSLoupe
91
* @param filter A RSFilter
94
rs_loupe_set_filter(RSLoupe *loupe, RSFilter *filter)
96
g_assert(RS_IS_LOUPE(loupe));
97
g_assert(RS_IS_FILTER(filter));
100
g_object_unref(loupe->filter);
102
loupe->filter = g_object_ref(filter);
106
* Set center coordinate of the RSLoupe, this will be clamped to filter size
107
* @param loupe A RSLoupe
108
* @param center_x Center of loupe on the X-axis
109
* @param center_y Center of loupe on the Y-axis
112
rs_loupe_set_coord(RSLoupe *loupe, gint center_x, gint center_y)
114
g_assert(RS_IS_LOUPE(loupe));
116
loupe->center_x = center_x;
117
loupe->center_y = center_y;
124
* Set display colorspace
125
* @param loupe A RSLoupe
126
* @param colorspace An RSColorSpace that should be used to display the content of the loupe
129
rs_loupe_set_colorspace(RSLoupe *loupe, RSColorSpace *display_color_space)
131
g_assert(RS_IS_LOUPE(loupe));
132
loupe->display_color_space = display_color_space;
136
rs_loupe_set_screen(RSLoupe* loupe, GdkScreen* screen, gint screen_num)
138
g_assert(RS_IS_LOUPE(loupe));
140
if (loupe->display_screen == screen && loupe->screen_num == screen_num)
143
loupe->display_screen = screen;
144
loupe->screen_num = screen_num;
145
const gint screen_width = gdk_screen_get_width(screen);
146
const gint screen_height = gdk_screen_get_height(screen);
148
const gint loupe_size = MIN(screen_width/4, screen_height/3) & 0xfffffff0;
150
/* Set screen and resize window */
151
gtk_window_set_screen(GTK_WINDOW(loupe), screen);
152
gtk_window_resize(GTK_WINDOW(loupe), loupe_size, loupe_size);
156
expose(GtkWidget *widget, GdkEventExpose *event, RSLoupe *loupe)
158
/* We always draw the full frame */
159
if (event->count > 0)
170
const gint distance_to_window = 50;
171
const gint distance_to_border = 20;
173
/* Get cursor position */
174
gint cursor_x=0, cursor_y=0;
175
gdk_display_get_pointer(gdk_display_get_default(), &loupe->display_screen, &cursor_x, &cursor_y, NULL);
177
/* Get window size */
178
gint window_width, window_height;
179
gtk_window_get_size(GTK_WINDOW(loupe), &window_width, &window_height);
181
/* Get screen size */
182
GdkScreen *screen = loupe->display_screen;
183
const gint screen_width = gdk_screen_get_width(screen);
184
const gint screen_height = gdk_screen_get_height(screen);
188
if ((cursor_x - window_width - distance_to_window) < distance_to_border)
189
loupe->left = !loupe->left;
193
if ((cursor_x + window_width + distance_to_window) > (screen_width - distance_to_border))
194
loupe->left = !loupe->left;
199
if ((cursor_y - window_height - distance_to_window) < distance_to_border)
200
loupe->atop = !loupe->atop;
204
if ((cursor_y + window_height + distance_to_window) > (screen_height - distance_to_border))
205
loupe->atop = !loupe->atop;
207
gint place_x, place_y;
210
place_x = cursor_x - window_width - distance_to_window;
212
place_x = cursor_x + distance_to_window;
215
place_y = cursor_y - window_height - distance_to_window;
217
place_y = cursor_y + distance_to_window;
219
gtk_window_move(GTK_WINDOW(loupe), place_x, place_y);
223
redraw(RSLoupe *loupe)
228
if (!GTK_WIDGET_DRAWABLE(loupe->canvas))
231
GdkDrawable *drawable = GDK_DRAWABLE(loupe->canvas->window);
232
GdkGC *gc = gdk_gc_new(drawable);
236
rs_filter_get_size_simple(loupe->filter, RS_FILTER_REQUEST_QUICK, &width, &height);
238
/* Get window size */
239
gint window_width, window_height;
240
gtk_window_get_size(GTK_WINDOW(loupe), &window_width, &window_height);
242
/* Create request ROI */
243
RSFilterRequest *request = rs_filter_request_new();
245
roi.x = CLAMP(loupe->center_x - window_width/2, 0, width-window_width-1);
246
roi.y = CLAMP(loupe->center_y - window_height/2, 0, height-window_height-1);
247
roi.width = window_width;
248
roi.height = window_height;
249
rs_filter_request_set_roi(request, &roi);
250
rs_filter_param_set_object(RS_FILTER_PARAM(request), "colorspace", loupe->display_color_space);
252
RSFilterResponse *response = rs_filter_get_image8(loupe->filter, request);
253
GdkPixbuf *buffer = rs_filter_response_get_image8(response);
254
g_object_unref(response);
256
g_object_unref(request);
258
gdk_draw_pixbuf(drawable, gc, buffer, roi.x, roi.y, 0, 0, roi.width, roi.height, GDK_RGB_DITHER_NONE, 0, 0);
261
static const GdkColor black = {0,0,0,0};
262
gdk_gc_set_foreground(gc, &black);
263
gdk_draw_rectangle(drawable, gc, FALSE, 0, 0, roi.width-1, roi.height-1);
265
g_object_unref(buffer);