~ubuntu-branches/ubuntu/vivid/rawstudio/vivid

« back to all changes in this revision

Viewing changes to src/rs-loupe.c

  • Committer: Bazaar Package Importer
  • Author(s): Bernd Zeimetz
  • Date: 2011-07-28 17:36:32 UTC
  • mfrom: (2.1.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20110728173632-5czluz9ye3c83zc5
Tags: 2.0-1
* [3750b2cf] Merge commit 'upstream/2.0'
* [63637468] Removing Patch, not necessary anymore.
* [2fb580dc] Add new build-dependencies.
* [c57d953b] Run dh_autoreconf due to patches in configure.in
* [13febe39] Add patch to remove the libssl requirement.
* [5ae773fe] Replace libjpeg62-dev by libjpeg8-dev :)
* [1969d755] Don't build static libraries.
* [7cfe0a2e] Add a patch to fix the plugin directory path.
  As plugins are shared libraries, they need to go into /usr/lib,
  not into /usr/share.
  Thanks to Andrew McMillan
* [c1d0d9dd] Don't install .la files for all plugins and libraries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * * Copyright (C) 2006-2011 Anders Brander <anders@brander.dk>, 
 
3
 * * Anders Kvist <akv@lnxbx.dk> and Klaus Post <klauspost@gmail.com>
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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.
 
18
 */
 
19
 
 
20
#include <rawstudio.h>
 
21
#include "rs-loupe.h"
 
22
 
 
23
G_DEFINE_TYPE (RSLoupe, rs_loupe, GTK_TYPE_WINDOW)
 
24
 
 
25
static gboolean expose(GtkWidget *widget, GdkEventExpose *event, RSLoupe *loupe);
 
26
static void move(RSLoupe *loupe);
 
27
static void redraw(RSLoupe *loupe);
 
28
 
 
29
static void
 
30
rs_loupe_finalize(GObject *object)
 
31
{
 
32
        RSLoupe *loupe = RS_LOUPE(object);
 
33
 
 
34
        if (loupe->filter)
 
35
                g_object_unref(loupe->filter);
 
36
 
 
37
        G_OBJECT_CLASS (rs_loupe_parent_class)->finalize (object);
 
38
}
 
39
 
 
40
static void
 
41
rs_loupe_class_init(RSLoupeClass *klass)
 
42
{
 
43
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
44
 
 
45
        object_class->finalize = rs_loupe_finalize;
 
46
}
 
47
 
 
48
static void
 
49
rs_loupe_init(RSLoupe *loupe)
 
50
{
 
51
        /* Get screen size */
 
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);
 
55
 
 
56
        const gint loupe_size = MIN(screen_width/4, screen_height/3);
 
57
 
 
58
        /* Initialize window */
 
59
        gtk_window_resize(GTK_WINDOW(loupe), loupe_size, loupe_size);
 
60
        gtk_window_set_keep_above(GTK_WINDOW(loupe), TRUE);
 
61
 
 
62
        /* We have to grab focus, otherwise window will not show up in fullscreen mode */
 
63
        g_object_set(GTK_WINDOW(loupe),
 
64
                "accept-focus", TRUE,
 
65
                "decorated", FALSE,
 
66
                "deletable", FALSE,
 
67
                "focus-on-map", FALSE,
 
68
                "skip-pager-hint", TRUE,
 
69
                "skip-taskbar-hint", TRUE,
 
70
                NULL);
 
71
 
 
72
        loupe->canvas = gtk_drawing_area_new();
 
73
        gtk_container_add(GTK_CONTAINER(loupe), loupe->canvas);
 
74
 
 
75
        g_signal_connect(loupe->canvas, "expose-event", G_CALLBACK(expose), loupe);
 
76
}
 
77
 
 
78
/**
 
79
 * Instantiates a new RSLoupe
 
80
 * @return A new RSLoupe
 
81
 */
 
82
RSLoupe *
 
83
rs_loupe_new(void)
 
84
{
 
85
        return g_object_new(RS_TYPE_LOUPE, "type", GTK_WINDOW_POPUP, NULL);
 
86
}
 
87
 
 
88
/**
 
89
 * Set the RSFilter a RSLoupe will get its image data from
 
90
 * @param loupe A RSLoupe
 
91
 * @param filter A RSFilter
 
92
 */
 
93
void
 
94
rs_loupe_set_filter(RSLoupe *loupe, RSFilter *filter)
 
95
{
 
96
        g_assert(RS_IS_LOUPE(loupe));
 
97
        g_assert(RS_IS_FILTER(filter));
 
98
 
 
99
        if (loupe->filter)
 
100
                g_object_unref(loupe->filter);
 
101
 
 
102
        loupe->filter = g_object_ref(filter);
 
103
}
 
104
 
 
105
/**
 
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
 
110
 */
 
111
void
 
112
rs_loupe_set_coord(RSLoupe *loupe, gint center_x, gint center_y)
 
113
{
 
114
        g_assert(RS_IS_LOUPE(loupe));
 
115
 
 
116
        loupe->center_x = center_x;
 
117
        loupe->center_y = center_y;
 
118
 
 
119
        move(loupe);
 
120
        redraw(loupe);
 
121
}
 
122
 
 
123
/**
 
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
 
127
 */
 
128
void
 
129
rs_loupe_set_colorspace(RSLoupe *loupe, RSColorSpace *display_color_space)
 
130
{
 
131
        g_assert(RS_IS_LOUPE(loupe));
 
132
        loupe->display_color_space = display_color_space;
 
133
}
 
134
 
 
135
void 
 
136
rs_loupe_set_screen(RSLoupe* loupe, GdkScreen* screen, gint screen_num)
 
137
{
 
138
        g_assert(RS_IS_LOUPE(loupe));
 
139
 
 
140
        if (loupe->display_screen == screen && loupe->screen_num == screen_num)
 
141
                return;
 
142
 
 
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);
 
147
 
 
148
        const gint loupe_size = MIN(screen_width/4, screen_height/3) & 0xfffffff0;
 
149
 
 
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);
 
153
}
 
154
 
 
155
static gboolean
 
156
expose(GtkWidget *widget, GdkEventExpose *event, RSLoupe *loupe)
 
157
{
 
158
        /* We always draw the full frame */
 
159
        if (event->count > 0)
 
160
                return TRUE;
 
161
 
 
162
        redraw(loupe);
 
163
 
 
164
        return TRUE;
 
165
}
 
166
 
 
167
static void
 
168
move(RSLoupe *loupe)
 
169
{
 
170
        const gint distance_to_window = 50;
 
171
        const gint distance_to_border = 20;
 
172
 
 
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);
 
176
 
 
177
        /* Get window size */
 
178
        gint window_width, window_height;
 
179
        gtk_window_get_size(GTK_WINDOW(loupe), &window_width, &window_height);
 
180
 
 
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);
 
185
 
 
186
        if (loupe->left)
 
187
        {
 
188
                if ((cursor_x - window_width - distance_to_window) < distance_to_border)
 
189
                        loupe->left = !loupe->left;
 
190
        }
 
191
        else
 
192
        {
 
193
                if ((cursor_x + window_width + distance_to_window) > (screen_width - distance_to_border))
 
194
                        loupe->left = !loupe->left;
 
195
        }
 
196
 
 
197
        if (loupe->atop)
 
198
        {
 
199
                if ((cursor_y - window_height - distance_to_window) < distance_to_border)
 
200
                        loupe->atop = !loupe->atop;
 
201
        }
 
202
        else
 
203
        {
 
204
                if ((cursor_y + window_height + distance_to_window) > (screen_height - distance_to_border))
 
205
                        loupe->atop = !loupe->atop;
 
206
        }
 
207
        gint place_x, place_y;
 
208
 
 
209
        if (loupe->left)
 
210
                place_x = cursor_x - window_width - distance_to_window;
 
211
        else
 
212
                place_x = cursor_x + distance_to_window;
 
213
 
 
214
        if (loupe->atop)
 
215
                place_y = cursor_y - window_height - distance_to_window;
 
216
        else
 
217
                place_y = cursor_y + distance_to_window;
 
218
 
 
219
        gtk_window_move(GTK_WINDOW(loupe), place_x, place_y);
 
220
}
 
221
 
 
222
static void
 
223
redraw(RSLoupe *loupe)
 
224
{
 
225
        if (!loupe->filter)
 
226
                return;
 
227
 
 
228
        if (!GTK_WIDGET_DRAWABLE(loupe->canvas))
 
229
                return;
 
230
 
 
231
        GdkDrawable *drawable = GDK_DRAWABLE(loupe->canvas->window);
 
232
        GdkGC *gc = gdk_gc_new(drawable);
 
233
 
 
234
        gint width;
 
235
        gint height;
 
236
        rs_filter_get_size_simple(loupe->filter, RS_FILTER_REQUEST_QUICK, &width, &height);
 
237
 
 
238
        /* Get window size */
 
239
        gint window_width, window_height;
 
240
        gtk_window_get_size(GTK_WINDOW(loupe), &window_width, &window_height);
 
241
 
 
242
        /* Create request ROI */
 
243
        RSFilterRequest *request = rs_filter_request_new();
 
244
        GdkRectangle roi;
 
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);
 
251
 
 
252
        RSFilterResponse *response = rs_filter_get_image8(loupe->filter, request);
 
253
        GdkPixbuf *buffer = rs_filter_response_get_image8(response);
 
254
        g_object_unref(response);
 
255
 
 
256
        g_object_unref(request);
 
257
 
 
258
        gdk_draw_pixbuf(drawable, gc, buffer, roi.x, roi.y, 0, 0, roi.width, roi.height, GDK_RGB_DITHER_NONE, 0, 0);
 
259
 
 
260
        /* Draw border */
 
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);
 
264
 
 
265
        g_object_unref(buffer);
 
266
        g_object_unref(gc);
 
267
}