Bug Summary

File:src/eoc-scroll-view.c
Warning:line 1778, column 2
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name eoc-scroll-view.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib/llvm-14/lib/clang/14.0.6 -D HAVE_CONFIG_H -I . -I .. -I . -I .. -I ../jpegutils -I ../cut-n-paste/toolbar-editor -D G_LOG_DOMAIN="EOC" -D EOC_DATA_DIR="/usr/local/share/eoc" -D EOC_LOCALE_DIR="/usr/local/share/locale" -D EOC_PLUGIN_DIR="/usr/local/lib/eoc/plugins" -D LIBDIR="/usr/local/lib" -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/cafe-desktop-2.0 -I /usr/include/startup-notification-1.0 -I /usr/include/dconf -I /usr/include/ctk-3.0/unix-print -I /usr/local/include/libbean-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/exempi-2.0 -I /usr/include/librsvg-2.0 -D PIC -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-06-18-161645-31336-1 -x c eoc-scroll-view.c
1#ifdef HAVE_CONFIG_H1
2#include <config.h>
3#endif
4
5#include <stdlib.h>
6#include <math.h>
7#include <gdk-pixbuf/gdk-pixbuf.h>
8#include <cdk/cdkkeysyms.h>
9#ifdef HAVE_RSVG1
10#include <librsvg/rsvg.h>
11#endif
12
13#include "eoc-config-keys.h"
14#include "eoc-enum-types.h"
15#include "eoc-marshal.h"
16#include "eoc-scroll-view.h"
17#include "eoc-debug.h"
18#include "zoom.h"
19
20#include <cdk/cdk.h>
21
22/* Maximum size of delayed repaint rectangles */
23#define PAINT_RECT_WIDTH128 128
24#define PAINT_RECT_HEIGHT128 128
25
26/* Scroll step increment */
27#define SCROLL_STEP_SIZE32 32
28
29/* Maximum zoom factor */
30#define MAX_ZOOM_FACTOR20 20
31#define MIN_ZOOM_FACTOR0.02 0.02
32
33#define CHECK_MEDIUM8 8
34#define CHECK_BLACK"#000000" "#000000"
35#define CHECK_DARK"#555555" "#555555"
36#define CHECK_GRAY"#808080" "#808080"
37#define CHECK_LIGHT"#cccccc" "#cccccc"
38#define CHECK_WHITE"#ffffff" "#ffffff"
39
40/* Default increment for zooming. The current zoom factor is multiplied or
41 * divided by this amount on every zooming step. For consistency, you should
42 * use the same value elsewhere in the program.
43 */
44#define IMAGE_VIEW_ZOOM_MULTIPLIER1.05 1.05
45
46/* States for automatically adjusting the zoom factor */
47typedef enum {
48 ZOOM_MODE_FIT, /* Image is fitted to scroll view even if the latter changes size */
49 ZOOM_MODE_FREE /* The image remains at its current zoom factor even if the scrollview changes size */
50} ZoomMode;
51
52/* Signal IDs */
53enum {
54 SIGNAL_ZOOM_CHANGED,
55 SIGNAL_LAST
56};
57
58static guint view_signals [SIGNAL_LAST] = { 0 };
59
60typedef enum {
61 EOC_SCROLL_VIEW_CURSOR_NORMAL,
62 EOC_SCROLL_VIEW_CURSOR_HIDDEN,
63 EOC_SCROLL_VIEW_CURSOR_DRAG
64} EocScrollViewCursor;
65
66/* Drag 'n Drop */
67static CtkTargetEntry target_table[] = {
68 { "text/uri-list", 0, 0},
69};
70
71enum {
72 PROP_0,
73 PROP_ANTIALIAS_IN,
74 PROP_ANTIALIAS_OUT,
75 PROP_BACKGROUND_COLOR,
76 PROP_IMAGE,
77 PROP_SCROLLWHEEL_ZOOM,
78 PROP_TRANSP_COLOR,
79 PROP_TRANSPARENCY_STYLE,
80 PROP_USE_BG_COLOR,
81 PROP_ZOOM_MULTIPLIER
82};
83
84/* Private part of the EocScrollView structure */
85struct _EocScrollViewPrivate {
86 /* some widgets we rely on */
87 CtkWidget *display;
88 CtkAdjustment *hadj;
89 CtkAdjustment *vadj;
90 CtkWidget *hbar;
91 CtkWidget *vbar;
92 CtkWidget *menu;
93
94 /* actual image */
95 EocImage *image;
96 guint image_changed_id;
97 guint frame_changed_id;
98 GdkPixbuf *pixbuf;
99 cairo_surface_t *surface;
100
101 /* scale factor */
102 gint scale;
103
104 /* zoom mode, either ZOOM_MODE_FIT or ZOOM_MODE_FREE */
105 ZoomMode zoom_mode;
106
107 /* whether to allow zoom > 1.0 on zoom fit */
108 gboolean upscale;
109
110 /* the actual zoom factor */
111 double zoom;
112
113 /* the minimum possible (reasonable) zoom factor */
114 double min_zoom;
115
116 /* Current scrolling offsets */
117 int xofs, yofs;
118
119 /* handler ID for paint idle callback */
120 guint idle_id;
121
122 /* Interpolation type when zoomed in*/
123 cairo_filter_t interp_type_in;
124
125 /* Interpolation type when zoomed out*/
126 cairo_filter_t interp_type_out;
127
128 /* Scroll wheel zoom */
129 gboolean scroll_wheel_zoom;
130
131 /* Scroll wheel zoom */
132 gdouble zoom_multiplier;
133
134 /* dragging stuff */
135 int drag_anchor_x, drag_anchor_y;
136 int drag_ofs_x, drag_ofs_y;
137 guint dragging : 1;
138
139 /* how to indicate transparency in images */
140 EocTransparencyStyle transp_style;
141 CdkRGBA transp_color;
142
143 /* the type of the cursor we are currently showing */
144 EocScrollViewCursor cursor;
145
146 gboolean use_bg_color;
147 CdkRGBA *background_color;
148 CdkRGBA *override_bg_color;
149
150 cairo_surface_t *background_surface;
151
152 /* Two-pass filtering */
153 GSource *hq_redraw_timeout_source;
154 gboolean force_unfiltered;
155};
156
157static void scroll_by (EocScrollView *view, int xofs, int yofs);
158static void set_zoom_fit (EocScrollView *view);
159/* static void request_paint_area (EocScrollView *view, CdkRectangle *area); */
160static void set_minimum_zoom_factor (EocScrollView *view);
161static void view_on_drag_begin_cb (CtkWidget *widget, CdkDragContext *context,
162 gpointer user_data);
163static void view_on_drag_data_get_cb (CtkWidget *widget,
164 CdkDragContext*drag_context,
165 CtkSelectionData *data, guint info,
166 guint time, gpointer user_data);
167
168static gboolean _eoc_cdk_rgba_equal0 (const CdkRGBA *a, const CdkRGBA *b);
169
170G_DEFINE_TYPE_WITH_PRIVATE (EocScrollView, eoc_scroll_view, CTK_TYPE_GRID)static void eoc_scroll_view_init (EocScrollView *self); static
void eoc_scroll_view_class_init (EocScrollViewClass *klass);
static GType eoc_scroll_view_get_type_once (void); static gpointer
eoc_scroll_view_parent_class = ((void*)0); static gint EocScrollView_private_offset
; static void eoc_scroll_view_class_intern_init (gpointer klass
) { eoc_scroll_view_parent_class = g_type_class_peek_parent (
klass); if (EocScrollView_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EocScrollView_private_offset); eoc_scroll_view_class_init
((EocScrollViewClass*) klass); } __attribute__ ((__unused__)
) static inline gpointer eoc_scroll_view_get_instance_private
(EocScrollView *self) { return (((gpointer) ((guint8*) (self
) + (glong) (EocScrollView_private_offset)))); } GType eoc_scroll_view_get_type
(void) { static gsize static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0));
(!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = eoc_scroll_view_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eoc_scroll_view_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((ctk_grid_get_type ()), g_intern_static_string ("EocScrollView"
), sizeof (EocScrollViewClass), (GClassInitFunc)(void (*)(void
)) eoc_scroll_view_class_intern_init, sizeof (EocScrollView),
(GInstanceInitFunc)(void (*)(void)) eoc_scroll_view_init, (GTypeFlags
) 0); { {{ EocScrollView_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (EocScrollViewPrivate)); };} } return
g_define_type_id; }
171
172/*===================================
173 widget size changing handler &
174 util functions
175 ---------------------------------*/
176
177static cairo_surface_t *
178create_surface_from_pixbuf (EocScrollView *view, GdkPixbuf *pixbuf)
179{
180 cairo_surface_t *surface;
181
182 surface = cdk_cairo_surface_create_from_pixbuf (pixbuf,
183 view->priv->scale,
184 ctk_widget_get_window (view->priv->display));
185
186 return surface;
187}
188
189/* Disconnects from the EocImage and removes references to it */
190static void
191free_image_resources (EocScrollView *view)
192{
193 EocScrollViewPrivate *priv;
194
195 priv = view->priv;
196
197 if (priv->image_changed_id > 0) {
198 g_signal_handler_disconnect (G_OBJECT (priv->image)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->image)), (((GType) ((20) << (2))))))))
, priv->image_changed_id);
199 priv->image_changed_id = 0;
200 }
201
202 if (priv->frame_changed_id > 0) {
203 g_signal_handler_disconnect (G_OBJECT (priv->image)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->image)), (((GType) ((20) << (2))))))))
, priv->frame_changed_id);
204 priv->frame_changed_id = 0;
205 }
206
207 if (priv->image != NULL((void*)0)) {
208 eoc_image_data_unref (priv->image);
209 priv->image = NULL((void*)0);
210 }
211
212 if (priv->pixbuf != NULL((void*)0)) {
213 g_object_unref (priv->pixbuf);
214 priv->pixbuf = NULL((void*)0);
215 }
216
217 if (priv->surface !=NULL((void*)0)) {
218 cairo_surface_destroy (priv->surface);
219 priv->surface = NULL((void*)0);
220 }
221}
222
223/* Computes the size in pixels of the scaled image */
224static void
225compute_scaled_size (EocScrollView *view, double zoom, int *width, int *height)
226{
227 EocScrollViewPrivate *priv;
228
229 priv = view->priv;
230
231 if (priv->pixbuf) {
232 *width = floor (gdk_pixbuf_get_width (priv->pixbuf) / priv->scale * zoom + 0.5);
233 *height = floor (gdk_pixbuf_get_height (priv->pixbuf) / priv->scale * zoom + 0.5);
234 } else
235 *width = *height = 0;
236}
237
238/* Computes the offsets for the new zoom value so that they keep the image
239 * centered on the view.
240 */
241static void
242compute_center_zoom_offsets (EocScrollView *view,
243 double old_zoom, double new_zoom,
244 int width, int height,
245 double zoom_x_anchor, double zoom_y_anchor,
246 int *xofs, int *yofs)
247{
248 EocScrollViewPrivate *priv;
249 int old_scaled_width, old_scaled_height;
250 int new_scaled_width, new_scaled_height;
251 double view_cx, view_cy;
252
253 priv = view->priv;
254
255 compute_scaled_size (view, old_zoom,
256 &old_scaled_width, &old_scaled_height);
257
258 if (old_scaled_width < width)
259 view_cx = (zoom_x_anchor * old_scaled_width) / old_zoom;
260 else
261 view_cx = (priv->xofs + zoom_x_anchor * width) / old_zoom;
262
263 if (old_scaled_height < height)
264 view_cy = (zoom_y_anchor * old_scaled_height) / old_zoom;
265 else
266 view_cy = (priv->yofs + zoom_y_anchor * height) / old_zoom;
267
268 compute_scaled_size (view, new_zoom,
269 &new_scaled_width, &new_scaled_height);
270
271 if (new_scaled_width < width)
272 *xofs = 0;
273 else {
274 *xofs = floor (view_cx * new_zoom - zoom_x_anchor * width + 0.5);
275 if (*xofs < 0)
276 *xofs = 0;
277 }
278
279 if (new_scaled_height < height)
280 *yofs = 0;
281 else {
282 *yofs = floor (view_cy * new_zoom - zoom_y_anchor * height + 0.5);
283 if (*yofs < 0)
284 *yofs = 0;
285 }
286}
287
288/* Sets the scrollbar values based on the current scrolling offset */
289static void
290update_scrollbar_values (EocScrollView *view)
291{
292 EocScrollViewPrivate *priv;
293 int scaled_width, scaled_height;
294 gdouble page_size,page_increment,step_increment;
295 gdouble lower, upper;
296 CtkAllocation allocation;
297
298 priv = view->priv;
299
300 if (!ctk_widget_get_visible (CTK_WIDGET (priv->hbar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->hbar)), ((ctk_widget_get_type ()))))))
)
301 && !ctk_widget_get_visible (CTK_WIDGET (priv->vbar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->vbar)), ((ctk_widget_get_type ()))))))
))
302 return;
303
304 compute_scaled_size (view, priv->zoom, &scaled_width, &scaled_height);
305 ctk_widget_get_allocation (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
, &allocation);
306
307 if (ctk_widget_get_visible (CTK_WIDGET (priv->hbar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->hbar)), ((ctk_widget_get_type ()))))))
)) {
308 /* Set scroll increments */
309 page_size = MIN (scaled_width, allocation.width)(((scaled_width) < (allocation.width)) ? (scaled_width) : (
allocation.width))
;
310
311 page_increment = allocation.width / 2;
312 step_increment = SCROLL_STEP_SIZE32;
313
314 /* Set scroll bounds and new offsets */
315 lower = 0;
316 upper = scaled_width;
317 priv->xofs = CLAMP (priv->xofs, 0, upper - page_size)(((priv->xofs) > (upper - page_size)) ? (upper - page_size
) : (((priv->xofs) < (0)) ? (0) : (priv->xofs)))
;
318
319 g_signal_handlers_block_matched (
320 priv->hadj, G_SIGNAL_MATCH_DATA,
321 0, 0, NULL((void*)0), NULL((void*)0), view);
322
323 ctk_adjustment_configure (priv->hadj, priv->xofs, lower,
324 upper, step_increment,
325 page_increment, page_size);
326
327 g_signal_handlers_unblock_matched (
328 priv->hadj, G_SIGNAL_MATCH_DATA,
329 0, 0, NULL((void*)0), NULL((void*)0), view);
330 }
331
332 if (ctk_widget_get_visible (CTK_WIDGET (priv->vbar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->vbar)), ((ctk_widget_get_type ()))))))
)) {
333 page_size = MIN (scaled_height, allocation.height)(((scaled_height) < (allocation.height)) ? (scaled_height)
: (allocation.height))
;
334 page_increment = allocation.height / 2;
335 step_increment = SCROLL_STEP_SIZE32;
336
337 lower = 0;
338 upper = scaled_height;
339 priv->yofs = CLAMP (priv->yofs, 0, upper - page_size)(((priv->yofs) > (upper - page_size)) ? (upper - page_size
) : (((priv->yofs) < (0)) ? (0) : (priv->yofs)))
;
340
341 g_signal_handlers_block_matched (
342 priv->vadj, G_SIGNAL_MATCH_DATA,
343 0, 0, NULL((void*)0), NULL((void*)0), view);
344
345 ctk_adjustment_configure (priv->vadj, priv->yofs, lower,
346 upper, step_increment,
347 page_increment, page_size);
348
349 g_signal_handlers_unblock_matched (
350 priv->vadj, G_SIGNAL_MATCH_DATA,
351 0, 0, NULL((void*)0), NULL((void*)0), view);
352 }
353}
354
355static void
356eoc_scroll_view_set_cursor (EocScrollView *view, EocScrollViewCursor new_cursor)
357{
358 CdkCursor *cursor = NULL((void*)0);
359 CdkDisplay *display;
360 CtkWidget *widget;
361
362 if (view->priv->cursor == new_cursor) {
363 return;
364 }
365
366 widget = ctk_widget_get_toplevel (CTK_WIDGET (view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), ((ctk_widget_get_type ()))))))
);
367 display = ctk_widget_get_display (widget);
368 view->priv->cursor = new_cursor;
369
370 switch (new_cursor) {
371 case EOC_SCROLL_VIEW_CURSOR_NORMAL:
372 cdk_window_set_cursor (ctk_widget_get_window (widget), NULL((void*)0));
373 break;
374 case EOC_SCROLL_VIEW_CURSOR_HIDDEN:
375 cursor = cdk_cursor_new_for_display (display, CDK_BLANK_CURSOR);
376 break;
377 case EOC_SCROLL_VIEW_CURSOR_DRAG:
378 cursor = cdk_cursor_new_for_display (display, CDK_FLEUR);
379 break;
380 }
381
382 if (cursor) {
383 cdk_window_set_cursor (ctk_widget_get_window (widget), cursor);
384 g_object_unref (cursor);
385 cdk_display_flush (display);
386 }
387}
388
389/* Changes visibility of the scrollbars based on the zoom factor and the
390 * specified allocation, or the current allocation if NULL is specified.
391 */
392static void
393check_scrollbar_visibility (EocScrollView *view, CtkAllocation *alloc)
394{
395 EocScrollViewPrivate *priv;
396 int bar_height;
397 int bar_width;
398 int img_width;
399 int img_height;
400 CtkRequisition req;
401 int width, height;
402 gboolean hbar_visible, vbar_visible;
403
404 priv = view->priv;
405
406 if (alloc) {
407 width = alloc->width;
408 height = alloc->height;
409 } else {
410 CtkAllocation allocation;
411
412 ctk_widget_get_allocation (CTK_WIDGET (view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), ((ctk_widget_get_type ()))))))
, &allocation);
413 width = allocation.width;
414 height = allocation.height;
415 }
416
417 compute_scaled_size (view, priv->zoom, &img_width, &img_height);
418
419 /* this should work fairly well in this special case for scrollbars */
420 ctk_widget_get_preferred_size (priv->hbar, &req, NULL((void*)0));
421 bar_height = req.height;
422 ctk_widget_get_preferred_size (priv->vbar, &req, NULL((void*)0));
423 bar_width = req.width;
424
425 eoc_debug_message (DEBUG_WINDOWEOC_DEBUG_WINDOW, "eoc-scroll-view.c", 425, ((const char*) (__func__
))
, "Widget Size allocate: %i, %i Bar: %i, %i\n",
426 width, height, bar_width, bar_height);
427
428 hbar_visible = vbar_visible = FALSE(0);
429 if (priv->zoom_mode == ZOOM_MODE_FIT)
430 hbar_visible = vbar_visible = FALSE(0);
431 else if (img_width <= width && img_height <= height)
432 hbar_visible = vbar_visible = FALSE(0);
433 else if (img_width > width && img_height > height)
434 hbar_visible = vbar_visible = TRUE(!(0));
435 else if (img_width > width) {
436 hbar_visible = TRUE(!(0));
437 if (img_height <= (height - bar_height))
438 vbar_visible = FALSE(0);
439 else
440 vbar_visible = TRUE(!(0));
441 }
442 else if (img_height > height) {
443 vbar_visible = TRUE(!(0));
444 if (img_width <= (width - bar_width))
445 hbar_visible = FALSE(0);
446 else
447 hbar_visible = TRUE(!(0));
448 }
449
450 if (hbar_visible != ctk_widget_get_visible (CTK_WIDGET (priv->hbar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->hbar)), ((ctk_widget_get_type ()))))))
))
451 g_object_set (G_OBJECT (priv->hbar)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->hbar)), (((GType) ((20) << (2))))))))
, "visible", hbar_visible, NULL((void*)0));
452
453 if (vbar_visible != ctk_widget_get_visible (CTK_WIDGET (priv->vbar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->vbar)), ((ctk_widget_get_type ()))))))
))
454 g_object_set (G_OBJECT (priv->vbar)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->vbar)), (((GType) ((20) << (2))))))))
, "visible", vbar_visible, NULL((void*)0));
455}
456
457#define DOUBLE_EQUAL_MAX_DIFF1e-6 1e-6
458#define DOUBLE_EQUAL(a,b)(fabs (a - b) < 1e-6) (fabs (a - b) < DOUBLE_EQUAL_MAX_DIFF1e-6)
459
460/* Returns whether the image is zoomed in */
461static gboolean
462is_zoomed_in (EocScrollView *view)
463{
464 EocScrollViewPrivate *priv;
465
466 priv = view->priv;
467 return priv->zoom - 1.0 > DOUBLE_EQUAL_MAX_DIFF1e-6;
468}
469
470/* Returns whether the image is zoomed out */
471static gboolean
472is_zoomed_out (EocScrollView *view)
473{
474 EocScrollViewPrivate *priv;
475
476 priv = view->priv;
477 return DOUBLE_EQUAL_MAX_DIFF1e-6 + priv->zoom - 1.0 < 0.0;
478}
479
480/* Returns wether the image is movable, that means if it is larger then
481 * the actual visible area.
482 */
483static gboolean
484is_image_movable (EocScrollView *view)
485{
486 EocScrollViewPrivate *priv;
487
488 priv = view->priv;
489
490 return (ctk_widget_get_visible (priv->hbar) || ctk_widget_get_visible (priv->vbar));
491}
492
493/*===================================
494 drawing core
495 ---------------------------------*/
496
497static void
498get_transparency_params (EocScrollView *view, int *size, CdkRGBA *color1, CdkRGBA *color2)
499{
500 EocScrollViewPrivate *priv;
501
502 priv = view->priv;
503
504 /* Compute transparency parameters */
505 switch (priv->transp_style) {
506 case EOC_TRANSP_BACKGROUND: {
507 /* Simply return fully transparent color */
508 color1->red = color1->green = color1->blue = color1->alpha = 0.0;
509 color2->red = color2->green = color2->blue = color2->alpha = 0.0;
510 break;
511 }
512
513 case EOC_TRANSP_CHECKED:
514 g_warn_if_fail (cdk_rgba_parse (color1, CHECK_GRAY))do { if (cdk_rgba_parse (color1, "#808080")) ; else g_warn_message
("EOC", "eoc-scroll-view.c", 514, ((const char*) (__func__))
, "cdk_rgba_parse (color1, CHECK_GRAY)"); } while (0)
;
515 g_warn_if_fail (cdk_rgba_parse (color2, CHECK_LIGHT))do { if (cdk_rgba_parse (color2, "#cccccc")) ; else g_warn_message
("EOC", "eoc-scroll-view.c", 515, ((const char*) (__func__))
, "cdk_rgba_parse (color2, CHECK_LIGHT)"); } while (0)
;
516 break;
517
518 case EOC_TRANSP_COLOR:
519 *color1 = *color2 = priv->transp_color;
520 break;
521
522 default:
523 g_assert_not_reached ()do { g_assertion_message_expr ("EOC", "eoc-scroll-view.c", 523
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
524 };
525
526 *size = CHECK_MEDIUM8;
527}
528
529static cairo_surface_t *
530create_background_surface (EocScrollView *view)
531{
532 int check_size;
533 CdkRGBA check_1;
534 CdkRGBA check_2;
535 cairo_surface_t *surface;
536
537 get_transparency_params (view, &check_size, &check_1, &check_2);
538 surface = cdk_window_create_similar_surface (ctk_widget_get_window (view->priv->display),
539 CAIRO_CONTENT_COLOR_ALPHA,
540 check_size * 2, check_size * 2);
541 cairo_t* cr = cairo_create (surface);
542
543 /* Use source operator to make fully transparent work */
544 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
545
546 cdk_cairo_set_source_rgba(cr, &check_1);
547 cairo_rectangle (cr, 0, 0, check_size, check_size);
548 cairo_rectangle (cr, check_size, check_size, check_size, check_size);
549 cairo_fill (cr);
550
551 cdk_cairo_set_source_rgba(cr, &check_2);
552 cairo_rectangle (cr, 0, check_size, check_size, check_size);
553 cairo_rectangle (cr, check_size, 0, check_size, check_size);
554 cairo_fill (cr);
555
556 cairo_destroy (cr);
557
558 return surface;
559}
560
561/* =======================================
562
563 scrolling stuff
564
565 --------------------------------------*/
566
567
568/* Scrolls the view to the specified offsets. */
569static void
570scroll_to (EocScrollView *view, int x, int y, gboolean change_adjustments)
571{
572 EocScrollViewPrivate *priv;
573 CtkAllocation allocation;
574 int xofs, yofs;
575 CdkWindow *window;
576
577 priv = view->priv;
578
579 /* Check bounds & Compute offsets */
580 if (ctk_widget_get_visible (priv->hbar)) {
581 x = CLAMP (x, 0, ctk_adjustment_get_upper (priv->hadj)(((x) > (ctk_adjustment_get_upper (priv->hadj) - ctk_adjustment_get_page_size
(priv->hadj))) ? (ctk_adjustment_get_upper (priv->hadj
) - ctk_adjustment_get_page_size (priv->hadj)) : (((x) <
(0)) ? (0) : (x)))
582 - ctk_adjustment_get_page_size (priv->hadj))(((x) > (ctk_adjustment_get_upper (priv->hadj) - ctk_adjustment_get_page_size
(priv->hadj))) ? (ctk_adjustment_get_upper (priv->hadj
) - ctk_adjustment_get_page_size (priv->hadj)) : (((x) <
(0)) ? (0) : (x)))
;
583 xofs = x - priv->xofs;
584 } else
585 xofs = 0;
586
587 if (ctk_widget_get_visible (priv->vbar)) {
588 y = CLAMP (y, 0, ctk_adjustment_get_upper (priv->vadj)(((y) > (ctk_adjustment_get_upper (priv->vadj) - ctk_adjustment_get_page_size
(priv->vadj))) ? (ctk_adjustment_get_upper (priv->vadj
) - ctk_adjustment_get_page_size (priv->vadj)) : (((y) <
(0)) ? (0) : (y)))
589 - ctk_adjustment_get_page_size (priv->vadj))(((y) > (ctk_adjustment_get_upper (priv->vadj) - ctk_adjustment_get_page_size
(priv->vadj))) ? (ctk_adjustment_get_upper (priv->vadj
) - ctk_adjustment_get_page_size (priv->vadj)) : (((y) <
(0)) ? (0) : (y)))
;
590 yofs = y - priv->yofs;
591 } else
592 yofs = 0;
593
594 if (xofs == 0 && yofs == 0)
595 return;
596
597 priv->xofs = x;
598 priv->yofs = y;
599
600 if (!ctk_widget_is_drawable (priv->display))
601 goto out;
602
603 ctk_widget_get_allocation (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
, &allocation);
604
605 if (abs (xofs) >= allocation.width || abs (yofs) >= allocation.height) {
606 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
607 goto out;
608 }
609
610 window = ctk_widget_get_window (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
611
612 cdk_window_scroll (window, -xofs, -yofs);
613
614 out:
615 if (!change_adjustments)
616 return;
617
618 g_signal_handlers_block_matched (
619 priv->hadj, G_SIGNAL_MATCH_DATA,
620 0, 0, NULL((void*)0), NULL((void*)0), view);
621 g_signal_handlers_block_matched (
622 priv->vadj, G_SIGNAL_MATCH_DATA,
623 0, 0, NULL((void*)0), NULL((void*)0), view);
624
625 ctk_adjustment_set_value (priv->hadj, x);
626 ctk_adjustment_set_value (priv->vadj, y);
627
628 g_signal_handlers_unblock_matched (
629 priv->hadj, G_SIGNAL_MATCH_DATA,
630 0, 0, NULL((void*)0), NULL((void*)0), view);
631 g_signal_handlers_unblock_matched (
632 priv->vadj, G_SIGNAL_MATCH_DATA,
633 0, 0, NULL((void*)0), NULL((void*)0), view);
634}
635
636/* Scrolls the image view by the specified offsets. Notifies the adjustments
637 * about their new values.
638 */
639static void
640scroll_by (EocScrollView *view, int xofs, int yofs)
641{
642 EocScrollViewPrivate *priv;
643
644 priv = view->priv;
645
646 scroll_to (view, priv->xofs + xofs, priv->yofs + yofs, TRUE(!(0)));
647}
648
649
650/* Callback used when an adjustment is changed */
651static void
652adjustment_changed_cb (CtkAdjustment *adj, gpointer data)
653{
654 EocScrollView *view;
655 EocScrollViewPrivate *priv;
656
657 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
658 priv = view->priv;
659
660 scroll_to (view, ctk_adjustment_get_value (priv->hadj),
661 ctk_adjustment_get_value (priv->vadj), FALSE(0));
662
663 ctk_widget_queue_resize (CTK_WIDGET (view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), ((ctk_widget_get_type ()))))))
);
664}
665
666
667/* Drags the image to the specified position */
668static void
669drag_to (EocScrollView *view, int x, int y)
670{
671 EocScrollViewPrivate *priv;
672 int dx, dy;
673
674 priv = view->priv;
675
676 dx = priv->drag_anchor_x - x;
677 dy = priv->drag_anchor_y - y;
678
679 x = priv->drag_ofs_x + dx;
680 y = priv->drag_ofs_y + dy;
681
682 scroll_to (view, x, y, TRUE(!(0)));
683}
684
685static void
686set_minimum_zoom_factor (EocScrollView *view)
687{
688 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
689
690 view->priv->min_zoom = MAX (1.0 / gdk_pixbuf_get_width (view->priv->pixbuf) / view->priv->scale,(((1.0 / gdk_pixbuf_get_width (view->priv->pixbuf) / view
->priv->scale) > ((((1.0 / gdk_pixbuf_get_height (view
->priv->pixbuf) / view->priv->scale) > (0.02))
? (1.0 / gdk_pixbuf_get_height (view->priv->pixbuf) / view
->priv->scale) : (0.02)))) ? (1.0 / gdk_pixbuf_get_width
(view->priv->pixbuf) / view->priv->scale) : ((((
1.0 / gdk_pixbuf_get_height (view->priv->pixbuf) / view
->priv->scale) > (0.02)) ? (1.0 / gdk_pixbuf_get_height
(view->priv->pixbuf) / view->priv->scale) : (0.02
))))
691 MAX(1.0 / gdk_pixbuf_get_height (view->priv->pixbuf) / view->priv->scale,(((1.0 / gdk_pixbuf_get_width (view->priv->pixbuf) / view
->priv->scale) > ((((1.0 / gdk_pixbuf_get_height (view
->priv->pixbuf) / view->priv->scale) > (0.02))
? (1.0 / gdk_pixbuf_get_height (view->priv->pixbuf) / view
->priv->scale) : (0.02)))) ? (1.0 / gdk_pixbuf_get_width
(view->priv->pixbuf) / view->priv->scale) : ((((
1.0 / gdk_pixbuf_get_height (view->priv->pixbuf) / view
->priv->scale) > (0.02)) ? (1.0 / gdk_pixbuf_get_height
(view->priv->pixbuf) / view->priv->scale) : (0.02
))))
692 MIN_ZOOM_FACTOR) )(((1.0 / gdk_pixbuf_get_width (view->priv->pixbuf) / view
->priv->scale) > ((((1.0 / gdk_pixbuf_get_height (view
->priv->pixbuf) / view->priv->scale) > (0.02))
? (1.0 / gdk_pixbuf_get_height (view->priv->pixbuf) / view
->priv->scale) : (0.02)))) ? (1.0 / gdk_pixbuf_get_width
(view->priv->pixbuf) / view->priv->scale) : ((((
1.0 / gdk_pixbuf_get_height (view->priv->pixbuf) / view
->priv->scale) > (0.02)) ? (1.0 / gdk_pixbuf_get_height
(view->priv->pixbuf) / view->priv->scale) : (0.02
))))
;
693 return;
694}
695
696/**
697 * set_zoom:
698 * @view: A scroll view.
699 * @zoom: Zoom factor.
700 * @have_anchor: Whether the anchor point specified by (@anchorx, @anchory)
701 * should be used.
702 * @anchorx: Horizontal anchor point in pixels.
703 * @anchory: Vertical anchor point in pixels.
704 *
705 * Sets the zoom factor for an image view. The anchor point can be used to
706 * specify the point that stays fixed when the image is zoomed. If @have_anchor
707 * is %TRUE, then (@anchorx, @anchory) specify the point relative to the image
708 * view widget's allocation that will stay fixed when zooming. If @have_anchor
709 * is %FALSE, then the center point of the image view will be used.
710 **/
711static void
712set_zoom (EocScrollView *view, double zoom,
713 gboolean have_anchor, int anchorx, int anchory)
714{
715 EocScrollViewPrivate *priv;
716 CtkAllocation allocation;
717 int xofs, yofs;
718 double x_rel, y_rel;
719
720 priv = view->priv;
721
722 if (priv->pixbuf == NULL((void*)0))
723 return;
724
725 if (zoom > MAX_ZOOM_FACTOR20)
726 zoom = MAX_ZOOM_FACTOR20;
727 else if (zoom < MIN_ZOOM_FACTOR0.02)
728 zoom = MIN_ZOOM_FACTOR0.02;
729
730 if (DOUBLE_EQUAL (priv->zoom, zoom)(fabs (priv->zoom - zoom) < 1e-6))
731 return;
732 if (DOUBLE_EQUAL (priv->zoom, priv->min_zoom)(fabs (priv->zoom - priv->min_zoom) < 1e-6) && zoom < priv->zoom)
733 return;
734
735 priv->zoom_mode = ZOOM_MODE_FREE;
736
737 ctk_widget_get_allocation (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
, &allocation);
738
739 /* compute new xofs/yofs values */
740 if (have_anchor) {
741 x_rel = (double) anchorx / allocation.width;
742 y_rel = (double) anchory / allocation.height;
743 } else {
744 x_rel = 0.5;
745 y_rel = 0.5;
746 }
747
748 compute_center_zoom_offsets (view, priv->zoom, zoom,
749 allocation.width, allocation.height,
750 x_rel, y_rel,
751 &xofs, &yofs);
752
753 /* set new values */
754 priv->xofs = xofs; /* (img_width * x_rel * zoom) - anchorx; */
755 priv->yofs = yofs; /* (img_height * y_rel * zoom) - anchory; */
756#if 0
757 g_print ("xofs: %i yofs: %i\n", priv->xofs, priv->yofs);
758#endif
759 if (zoom <= priv->min_zoom)
760 priv->zoom = priv->min_zoom;
761 else
762 priv->zoom = zoom;
763
764 /* we make use of the new values here */
765 check_scrollbar_visibility (view, NULL((void*)0));
766 update_scrollbar_values (view);
767
768 /* repaint the whole image */
769 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
770
771 g_signal_emit (view, view_signals [SIGNAL_ZOOM_CHANGED], 0, priv->zoom);
772}
773
774/* Zooms the image to fit the available allocation */
775static void
776set_zoom_fit (EocScrollView *view)
777{
778 EocScrollViewPrivate *priv;
779 CtkAllocation allocation;
780 double new_zoom;
781
782 priv = view->priv;
783
784 priv->zoom_mode = ZOOM_MODE_FIT;
785
786 if (!ctk_widget_get_mapped (CTK_WIDGET (view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), ((ctk_widget_get_type ()))))))
))
787 return;
788
789 if (priv->pixbuf == NULL((void*)0))
790 return;
791
792 ctk_widget_get_allocation (CTK_WIDGET(priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
, &allocation);
793
794 new_zoom = zoom_fit_scale (allocation.width, allocation.height,
795 gdk_pixbuf_get_width (priv->pixbuf) / priv->scale,
796 gdk_pixbuf_get_height (priv->pixbuf) / priv->scale,
797 priv->upscale);
798
799 if (new_zoom > MAX_ZOOM_FACTOR20)
800 new_zoom = MAX_ZOOM_FACTOR20;
801 else if (new_zoom < MIN_ZOOM_FACTOR0.02)
802 new_zoom = MIN_ZOOM_FACTOR0.02;
803
804 priv->zoom = new_zoom;
805 priv->xofs = 0;
806 priv->yofs = 0;
807
808 g_signal_emit (view, view_signals [SIGNAL_ZOOM_CHANGED], 0, priv->zoom);
809}
810
811/*===================================
812
813 internal signal callbacks
814
815 ---------------------------------*/
816
817/* Key press event handler for the image view */
818static gboolean
819display_key_press_event (CtkWidget *widget, CdkEventKey *event, gpointer data)
820{
821 EocScrollView *view;
822 EocScrollViewPrivate *priv;
823 CtkAllocation allocation;
824 gboolean do_zoom;
825 double zoom;
826 gboolean do_scroll;
827 int xofs, yofs;
828
829 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
830 priv = view->priv;
831
832 do_zoom = FALSE(0);
833 do_scroll = FALSE(0);
834 xofs = yofs = 0;
835 zoom = 1.0;
836
837 ctk_widget_get_allocation (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
, &allocation);
838
839 /* EocScrollView doesn't handle/have any Alt+Key combos */
840 if (event->state & CDK_MOD1_MASK) {
841 return FALSE(0);
842 }
843
844 switch (event->keyval) {
845 case CDK_KEY_Up0xff52:
846 do_scroll = TRUE(!(0));
847 xofs = 0;
848 yofs = -SCROLL_STEP_SIZE32;
849 break;
850
851 case CDK_KEY_Page_Up0xff55:
852 do_scroll = TRUE(!(0));
853 if (event->state & CDK_CONTROL_MASK) {
854 xofs = -(allocation.width * 3) / 4;
855 yofs = 0;
856 } else {
857 xofs = 0;
858 yofs = -(allocation.height * 3) / 4;
859 }
860 break;
861
862 case CDK_KEY_Down0xff54:
863 do_scroll = TRUE(!(0));
864 xofs = 0;
865 yofs = SCROLL_STEP_SIZE32;
866 break;
867
868 case CDK_KEY_Page_Down0xff56:
869 do_scroll = TRUE(!(0));
870 if (event->state & CDK_CONTROL_MASK) {
871 xofs = (allocation.width * 3) / 4;
872 yofs = 0;
873 } else {
874 xofs = 0;
875 yofs = (allocation.height * 3) / 4;
876 }
877 break;
878
879 case CDK_KEY_Left0xff51:
880 do_scroll = TRUE(!(0));
881 xofs = -SCROLL_STEP_SIZE32;
882 yofs = 0;
883 break;
884
885 case CDK_KEY_Right0xff53:
886 do_scroll = TRUE(!(0));
887 xofs = SCROLL_STEP_SIZE32;
888 yofs = 0;
889 break;
890
891 case CDK_KEY_plus0x02b:
892 case CDK_KEY_equal0x03d:
893 case CDK_KEY_KP_Add0xffab:
894 do_zoom = TRUE(!(0));
895 zoom = priv->zoom * priv->zoom_multiplier;
896 break;
897
898 case CDK_KEY_minus0x02d:
899 case CDK_KEY_KP_Subtract0xffad:
900 do_zoom = TRUE(!(0));
901 zoom = priv->zoom / priv->zoom_multiplier;
902 break;
903
904 case CDK_KEY_10x031:
905 do_zoom = TRUE(!(0));
906 zoom = 1.0;
907 break;
908
909 default:
910 return FALSE(0);
911 }
912
913 if (do_zoom) {
914 CdkSeat *seat;
915 CdkDevice *device;
916 gint x, y;
917
918 seat = cdk_display_get_default_seat (ctk_widget_get_display (widget));
919 device = cdk_seat_get_pointer (seat);
920
921 cdk_window_get_device_position (ctk_widget_get_window (widget), device,
922 &x, &y, NULL((void*)0));
923 set_zoom (view, zoom, TRUE(!(0)), x, y);
924 }
925
926 if (do_scroll)
927 scroll_by (view, xofs, yofs);
928
929 return TRUE(!(0));
930}
931
932
933/* Button press event handler for the image view */
934static gboolean
935eoc_scroll_view_button_press_event (CtkWidget *widget, CdkEventButton *event, gpointer data)
936{
937 EocScrollView *view;
938 EocScrollViewPrivate *priv;
939
940 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
941 priv = view->priv;
942
943 if (!ctk_widget_has_focus (priv->display))
944 ctk_widget_grab_focus (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
945
946 if (priv->dragging)
947 return FALSE(0);
948
949 switch (event->button) {
950 case 1:
951 case 2:
952 if (event->button == 1 && !priv->scroll_wheel_zoom &&
953 !(event->state & CDK_CONTROL_MASK))
954 break;
955
956 if (is_image_movable (view)) {
957 eoc_scroll_view_set_cursor (view, EOC_SCROLL_VIEW_CURSOR_DRAG);
958
959 priv->dragging = TRUE(!(0));
960 priv->drag_anchor_x = event->x;
961 priv->drag_anchor_y = event->y;
962
963 priv->drag_ofs_x = priv->xofs;
964 priv->drag_ofs_y = priv->yofs;
965
966 return TRUE(!(0));
967 }
968 default:
969 break;
970 }
971
972 return FALSE(0);
973}
974
975/* Button release event handler for the image view */
976static gboolean
977eoc_scroll_view_button_release_event (CtkWidget *widget, CdkEventButton *event, gpointer data)
978{
979 EocScrollView *view;
980 EocScrollViewPrivate *priv;
981
982 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
983 priv = view->priv;
984
985 if (!priv->dragging)
986 return FALSE(0);
987
988 switch (event->button) {
989 case 1:
990 case 2:
991 drag_to (view, event->x, event->y);
992 priv->dragging = FALSE(0);
993
994 eoc_scroll_view_set_cursor (view, EOC_SCROLL_VIEW_CURSOR_NORMAL);
995 break;
996
997 default:
998 break;
999 }
1000
1001 return TRUE(!(0));
1002}
1003
1004/* Scroll event handler for the image view. We zoom with an event without
1005 * modifiers rather than scroll; we use the Shift modifier to scroll.
1006 * Rationale: images are not primarily vertical, and in EOC you scan scroll by
1007 * dragging the image with button 1 anyways.
1008 */
1009static gboolean
1010eoc_scroll_view_scroll_event (CtkWidget *widget, CdkEventScroll *event, gpointer data)
1011{
1012 EocScrollView *view;
1013 EocScrollViewPrivate *priv;
1014 double zoom_factor;
1015 int xofs, yofs;
1016
1017 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
1018 priv = view->priv;
1019
1020 /* Compute zoom factor and scrolling offsets; we'll only use either of them */
1021 /* same as in ctkscrolledwindow.c */
1022 xofs = ctk_adjustment_get_page_increment (priv->hadj) / 2;
1023 yofs = ctk_adjustment_get_page_increment (priv->vadj) / 2;
1024
1025 switch (event->direction) {
1026 case CDK_SCROLL_UP:
1027 zoom_factor = priv->zoom_multiplier;
1028 xofs = 0;
1029 yofs = -yofs;
1030 break;
1031
1032 case CDK_SCROLL_LEFT:
1033 zoom_factor = 1.0 / priv->zoom_multiplier;
1034 xofs = -xofs;
1035 yofs = 0;
1036 break;
1037
1038 case CDK_SCROLL_DOWN:
1039 zoom_factor = 1.0 / priv->zoom_multiplier;
1040 xofs = 0;
1041 yofs = yofs;
1042 break;
1043
1044 case CDK_SCROLL_RIGHT:
1045 zoom_factor = priv->zoom_multiplier;
1046 xofs = xofs;
1047 yofs = 0;
1048 break;
1049
1050 default:
1051 g_assert_not_reached ()do { g_assertion_message_expr ("EOC", "eoc-scroll-view.c", 1051
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1052 return FALSE(0);
1053 }
1054
1055 if (priv->scroll_wheel_zoom) {
1056 if (event->state & CDK_SHIFT_MASK)
1057 scroll_by (view, yofs, xofs);
1058 else if (event->state & CDK_CONTROL_MASK)
1059 scroll_by (view, xofs, yofs);
1060 else
1061 set_zoom (view, priv->zoom * zoom_factor,
1062 TRUE(!(0)), event->x, event->y);
1063 } else {
1064 if (event->state & CDK_SHIFT_MASK)
1065 scroll_by (view, yofs, xofs);
1066 else if (event->state & CDK_CONTROL_MASK)
1067 set_zoom (view, priv->zoom * zoom_factor,
1068 TRUE(!(0)), event->x, event->y);
1069 else
1070 scroll_by (view, xofs, yofs);
1071 }
1072
1073 return TRUE(!(0));
1074}
1075
1076/* Motion event handler for the image view */
1077static gboolean
1078eoc_scroll_view_motion_event (CtkWidget *widget, CdkEventMotion *event, gpointer data)
1079{
1080 EocScrollView *view;
1081 EocScrollViewPrivate *priv;
1082 gint x, y;
1083 CdkModifierType mods;
1084
1085 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
1086 priv = view->priv;
1087
1088 if (!priv->dragging)
1089 return FALSE(0);
1090
1091 if (event->is_hint)
1092 cdk_window_get_device_position (ctk_widget_get_window (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
), event->device, &x, &y, &mods);
1093 else {
1094 x = event->x;
1095 y = event->y;
1096 }
1097
1098 drag_to (view, x, y);
1099 return TRUE(!(0));
1100}
1101
1102static void
1103display_map_event (CtkWidget *widget, CdkEvent *event, gpointer data)
1104{
1105 EocScrollView *view;
1106 EocScrollViewPrivate *priv;
1107
1108 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
1109 priv = view->priv;
1110
1111 eoc_debug (DEBUG_WINDOWEOC_DEBUG_WINDOW, "eoc-scroll-view.c", 1111, ((const char*) (
__func__))
);
1112
1113 set_zoom_fit (view);
1114 check_scrollbar_visibility (view, NULL((void*)0));
1115 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1116}
1117
1118static void
1119eoc_scroll_view_size_allocate (CtkWidget *widget, CtkAllocation *alloc)
1120{
1121 EocScrollView *view;
1122
1123 view = EOC_SCROLL_VIEW (widget)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((eoc_scroll_view_get_type ()))))))
;
1124 check_scrollbar_visibility (view, alloc);
1125
1126 CTK_WIDGET_CLASS (eoc_scroll_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((eoc_scroll_view_parent_class)), ((ctk_widget_get_type ()
))))))
->size_allocate (widget
1127 ,alloc);
1128}
1129
1130static void
1131display_size_change (CtkWidget *widget, CdkEventConfigure *event, gpointer data)
1132{
1133 EocScrollView *view;
1134 EocScrollViewPrivate *priv;
1135
1136 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
1137 priv = view->priv;
1138
1139 if (priv->zoom_mode == ZOOM_MODE_FIT) {
1140 CtkAllocation alloc;
1141
1142 alloc.width = event->width;
1143 alloc.height = event->height;
1144
1145 set_zoom_fit (view);
1146 check_scrollbar_visibility (view, &alloc);
1147 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1148 } else {
1149 int scaled_width, scaled_height;
1150 int x_offset = 0;
1151 int y_offset = 0;
1152
1153 compute_scaled_size (view, priv->zoom, &scaled_width, &scaled_height);
1154
1155 if (priv->xofs + event->width > scaled_width)
1156 x_offset = scaled_width - event->width - priv->xofs;
1157
1158 if (priv->yofs + event->height > scaled_height)
1159 y_offset = scaled_height - event->height - priv->yofs;
1160
1161 scroll_by (view, x_offset, y_offset);
1162 }
1163
1164 update_scrollbar_values (view);
1165}
1166
1167
1168static gboolean
1169eoc_scroll_view_focus_in_event (CtkWidget *widget,
1170 CdkEventFocus *event,
1171 gpointer data)
1172{
1173 g_signal_stop_emission_by_name (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
, "focus_in_event");
1174 return FALSE(0);
1175}
1176
1177static gboolean
1178eoc_scroll_view_focus_out_event (CtkWidget *widget,
1179 CdkEventFocus *event,
1180 gpointer data)
1181{
1182 g_signal_stop_emission_by_name (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
, "focus_out_event");
1183 return FALSE(0);
1184}
1185
1186static gboolean _hq_redraw_cb (gpointer user_data)
1187{
1188 EocScrollViewPrivate *priv = EOC_SCROLL_VIEW (user_data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((eoc_scroll_view_get_type ()))))))
->priv;
1189
1190 priv->force_unfiltered = FALSE(0);
1191 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1192
1193 priv->hq_redraw_timeout_source = NULL((void*)0);
1194 return G_SOURCE_REMOVE(0);
1195}
1196
1197static void
1198_clear_hq_redraw_timeout (EocScrollView *view)
1199{
1200 EocScrollViewPrivate *priv = view->priv;
1201
1202 if (priv->hq_redraw_timeout_source != NULL((void*)0)) {
1203 g_source_unref (priv->hq_redraw_timeout_source);
1204 g_source_destroy (priv->hq_redraw_timeout_source);
1205 }
1206
1207 priv->hq_redraw_timeout_source = NULL((void*)0);
1208}
1209
1210static void
1211_set_hq_redraw_timeout (EocScrollView *view)
1212{
1213 GSource *source;
1214
1215 _clear_hq_redraw_timeout (view);
1216
1217 source = g_timeout_source_new (200);
1218 g_source_set_callback (source, &_hq_redraw_cb, view, NULL((void*)0));
1219
1220 g_source_attach (source, NULL((void*)0));
1221
1222 view->priv->hq_redraw_timeout_source = source;
1223}
1224
1225static gboolean
1226display_draw (CtkWidget *widget, cairo_t *cr, gpointer data)
1227{
1228 const CdkRGBA *background_color = NULL((void*)0);
1229 EocScrollView *view;
1230 EocScrollViewPrivate *priv;
1231 CtkAllocation allocation;
1232 int scaled_width, scaled_height;
1233 int xofs, yofs;
1234
1235 g_return_val_if_fail (CTK_IS_DRAWING_AREA (widget), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((ctk_drawing_area_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "CTK_IS_DRAWING_AREA (widget)"); return ((0)); } } while (
0)
;
1236 g_return_val_if_fail (EOC_IS_SCROLL_VIEW (data), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((data)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (data)"); return ((0)); } } while (0)
;
1237
1238 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
1239
1240 priv = view->priv;
1241
1242 if (priv->pixbuf == NULL((void*)0))
1243 return TRUE(!(0));
1244
1245 compute_scaled_size (view, priv->zoom, &scaled_width, &scaled_height);
1246
1247 ctk_widget_get_allocation (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
, &allocation);
1248
1249 /* Compute image offsets with respect to the window */
1250
1251 if (scaled_width <= allocation.width)
1252 xofs = (allocation.width - scaled_width) / 2;
1253 else
1254 xofs = -priv->xofs;
1255
1256 if (scaled_height <= allocation.height)
1257 yofs = (allocation.height - scaled_height) / 2;
1258 else
1259 yofs = -priv->yofs;
1260
1261 eoc_debug_message (DEBUG_WINDOWEOC_DEBUG_WINDOW, "eoc-scroll-view.c", 1261, ((const char*) (
__func__))
, "zoom %.2f, xofs: %i, yofs: %i scaled w: %i h: %i\n",
1262 priv->zoom, xofs, yofs, scaled_width, scaled_height);
1263
1264 /* Paint the background */
1265 cairo_rectangle (cr, 0, 0, allocation.width, allocation.height);
1266 if (priv->transp_style != EOC_TRANSP_BACKGROUND)
1267 cairo_rectangle (cr, MAX (0, xofs)(((0) > (xofs)) ? (0) : (xofs)), MAX (0, yofs)(((0) > (yofs)) ? (0) : (yofs)),
1268 scaled_width, scaled_height);
1269 if (priv->override_bg_color != NULL((void*)0))
1270 background_color = priv->override_bg_color;
1271 else if (priv->use_bg_color)
1272 background_color = priv->background_color;
1273 if (background_color != NULL((void*)0))
1274 cairo_set_source_rgba (cr,
1275 background_color->red,
1276 background_color->green,
1277 background_color->blue,
1278 background_color->alpha);
1279 else
1280 cairo_set_source (cr, cdk_window_get_background_pattern (ctk_widget_get_window (priv->display)));
1281 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
1282 cairo_fill (cr);
1283
1284 if (gdk_pixbuf_get_has_alpha (priv->pixbuf)) {
1285 if (priv->background_surface == NULL((void*)0)) {
1286 priv->background_surface = create_background_surface (view);
1287 }
1288 cairo_set_source_surface (cr, priv->background_surface, xofs, yofs);
1289 cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
1290 cairo_rectangle (cr, xofs, yofs, scaled_width, scaled_height);
1291 cairo_fill (cr);
1292 }
1293
1294 /* Make sure the image is only drawn as large as needed.
1295 * This is especially necessary for SVGs where there might
1296 * be more image data available outside the image boundaries.
1297 */
1298 cairo_rectangle (cr, xofs, yofs, scaled_width, scaled_height);
1299 cairo_clip (cr);
1300
1301#ifdef HAVE_RSVG1
1302 if (eoc_image_is_svg (view->priv->image)) {
1303 cairo_matrix_t matrix, translate, scale, original;
1304 EocTransform *transform = eoc_image_get_transform (priv->image);
1305 cairo_matrix_init_identity (&matrix);
1306 if (transform) {
1307 cairo_matrix_t affine;
1308 double image_offset_x = 0., image_offset_y = 0.;
1309
1310 eoc_transform_get_affine (transform, &affine);
1311 cairo_matrix_multiply (&matrix, &affine, &matrix);
1312
1313 switch (eoc_transform_get_transform_type (transform)) {
1314 case EOC_TRANSFORM_ROT_90:
1315 case EOC_TRANSFORM_FLIP_HORIZONTAL:
1316 image_offset_x = (double) gdk_pixbuf_get_width (priv->pixbuf);
1317 break;
1318 case EOC_TRANSFORM_ROT_270:
1319 case EOC_TRANSFORM_FLIP_VERTICAL:
1320 image_offset_y = (double) gdk_pixbuf_get_height (priv->pixbuf);
1321 break;
1322 case EOC_TRANSFORM_ROT_180:
1323 case EOC_TRANSFORM_TRANSPOSE:
1324 case EOC_TRANSFORM_TRANSVERSE:
1325 image_offset_x = (double) gdk_pixbuf_get_width (priv->pixbuf);
1326 image_offset_y = (double) gdk_pixbuf_get_height (priv->pixbuf);
1327 break;
1328 case EOC_TRANSFORM_NONE:
1329 default:
1330 break;
1331 }
1332 cairo_matrix_init_translate (&translate, image_offset_x, image_offset_y);
1333 cairo_matrix_multiply (&matrix, &matrix, &translate);
1334 }
1335 /* Zoom factor for SVGs is already scaled, so scale back to application pixels. */
1336 cairo_matrix_init_scale (&scale, priv->zoom / priv->scale, priv->zoom / priv->scale);
1337 cairo_matrix_multiply (&matrix, &matrix, &scale);
1338 cairo_matrix_init_translate (&translate, xofs, yofs);
1339 cairo_matrix_multiply (&matrix, &matrix, &translate);
1340
1341 cairo_get_matrix (cr, &original);
1342 cairo_matrix_multiply (&matrix, &matrix, &original);
1343 cairo_set_matrix (cr, &matrix);
1344
1345 rsvg_handle_render_cairo (eoc_image_get_svg (priv->image), cr);
1346
1347 } else
1348#endif /* HAVE_RSVG */
1349 {
1350 cairo_filter_t interp_type;
1351
1352 if(!DOUBLE_EQUAL(priv->zoom, 1.0)(fabs (priv->zoom - 1.0) < 1e-6) && priv->force_unfiltered)
1353 {
1354 interp_type = CAIRO_FILTER_NEAREST;
1355 _set_hq_redraw_timeout(view);
1356 }
1357 else
1358 {
1359 if (is_zoomed_in (view))
1360 interp_type = priv->interp_type_in;
1361 else
1362 interp_type = priv->interp_type_out;
1363
1364 _clear_hq_redraw_timeout (view);
1365 priv->force_unfiltered = TRUE(!(0));
1366 }
1367 cairo_scale (cr, priv->zoom, priv->zoom);
1368 cairo_set_source_surface (cr, priv->surface, xofs/priv->zoom, yofs/priv->zoom);
1369 cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_PAD);
1370 if (is_zoomed_in (view) || is_zoomed_out (view))
1371 cairo_pattern_set_filter (cairo_get_source (cr), interp_type);
1372
1373 cairo_paint (cr);
1374 }
1375
1376 return TRUE(!(0));
1377}
1378
1379
1380/*==================================
1381
1382 image loading callbacks
1383
1384 -----------------------------------*/
1385
1386/* Use when the pixbuf in the view is changed, to keep a
1387 reference to it and create its cairo surface. */
1388static void
1389update_pixbuf (EocScrollView *view, GdkPixbuf *pixbuf)
1390{
1391 EocScrollViewPrivate *priv;
1392
1393 priv = view->priv;
1394
1395 if (priv->pixbuf != NULL((void*)0)) {
1396 g_object_unref (priv->pixbuf);
1397 priv->pixbuf = NULL((void*)0);
1398 }
1399
1400 priv->pixbuf = pixbuf;
1401
1402 if (priv->surface) {
1403 cairo_surface_destroy (priv->surface);
1404 }
1405 priv->surface = create_surface_from_pixbuf (view, priv->pixbuf);
1406}
1407
1408static void
1409image_changed_cb (EocImage *img, gpointer data)
1410{
1411 EocScrollViewPrivate *priv;
1412
1413 priv = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
->priv;
1414
1415 update_pixbuf (EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
, eoc_image_get_pixbuf (img));
1416
1417 set_zoom_fit (EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
);
1418 check_scrollbar_visibility (EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
, NULL((void*)0));
1419
1420 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1421}
1422
1423/*===================================
1424 public API
1425 ---------------------------------*/
1426
1427void
1428eoc_scroll_view_hide_cursor (EocScrollView *view)
1429{
1430 eoc_scroll_view_set_cursor (view, EOC_SCROLL_VIEW_CURSOR_HIDDEN);
1431}
1432
1433void
1434eoc_scroll_view_show_cursor (EocScrollView *view)
1435{
1436 eoc_scroll_view_set_cursor (view, EOC_SCROLL_VIEW_CURSOR_NORMAL);
1437}
1438
1439/* general properties */
1440void
1441eoc_scroll_view_set_zoom_upscale (EocScrollView *view, gboolean upscale)
1442{
1443 EocScrollViewPrivate *priv;
1444
1445 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
1446
1447 priv = view->priv;
1448
1449 if (priv->upscale != upscale) {
1450 priv->upscale = upscale;
1451
1452 if (priv->zoom_mode == ZOOM_MODE_FIT) {
1453 set_zoom_fit (view);
1454 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1455 }
1456 }
1457}
1458
1459void
1460eoc_scroll_view_set_antialiasing_in (EocScrollView *view, gboolean state)
1461{
1462 EocScrollViewPrivate *priv;
1463 cairo_filter_t new_interp_type;
1464
1465 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
1466
1467 priv = view->priv;
1468
1469 new_interp_type = state ? CAIRO_FILTER_GOOD : CAIRO_FILTER_NEAREST;
1470
1471 if (priv->interp_type_in != new_interp_type) {
1472 priv->interp_type_in = new_interp_type;
1473 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1474 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "antialiasing-in");
1475 }
1476}
1477
1478void
1479eoc_scroll_view_set_antialiasing_out (EocScrollView *view, gboolean state)
1480{
1481 EocScrollViewPrivate *priv;
1482 cairo_filter_t new_interp_type;
1483
1484 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
1485
1486 priv = view->priv;
1487
1488 new_interp_type = state ? CAIRO_FILTER_GOOD : CAIRO_FILTER_NEAREST;
1489
1490 if (priv->interp_type_out != new_interp_type) {
1491 priv->interp_type_out = new_interp_type;
1492 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1493 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "antialiasing-out");
1494
1495 }
1496}
1497
1498static void
1499_transp_background_changed (EocScrollView *view)
1500{
1501 EocScrollViewPrivate *priv = view->priv;
1502
1503 if (priv->pixbuf != NULL((void*)0) && gdk_pixbuf_get_has_alpha (priv->pixbuf)) {
1504 if (priv->background_surface) {
1505 cairo_surface_destroy (priv->background_surface);
1506 /* Will be recreated if needed during redraw */
1507 priv->background_surface = NULL((void*)0);
1508 }
1509 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1510 }
1511
1512}
1513
1514void
1515eoc_scroll_view_set_transparency_color (EocScrollView *view, CdkRGBA *color)
1516{
1517 EocScrollViewPrivate *priv;
1518
1519 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
1520
1521 priv = view->priv;
1522
1523 if (!_eoc_cdk_rgba_equal0 (&priv->transp_color, color)) {
1524 priv->transp_color = *color;
1525 if (priv->transp_style == EOC_TRANSP_COLOR)
1526 _transp_background_changed (view);
1527
1528 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "transparency-color");
1529 }
1530}
1531
1532void
1533eoc_scroll_view_set_transparency (EocScrollView *view,
1534 EocTransparencyStyle style)
1535{
1536 EocScrollViewPrivate *priv;
1537
1538 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
1539
1540 priv = view->priv;
1541
1542 if (priv->transp_style != style) {
1543 priv->transp_style = style;
1544 _transp_background_changed (view);
1545 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "transparency-style");
1546 }
1547}
1548
1549/* zoom api */
1550
1551static double preferred_zoom_levels[] = {
1552 1.0 / 100, 1.0 / 50, 1.0 / 20,
1553 1.0 / 10.0, 1.0 / 5.0, 1.0 / 3.0, 1.0 / 2.0, 1.0 / 1.5,
1554 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0,
1555 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0
1556};
1557static const gint n_zoom_levels = (sizeof (preferred_zoom_levels) / sizeof (double));
1558
1559void
1560eoc_scroll_view_zoom_in (EocScrollView *view, gboolean smooth)
1561{
1562 EocScrollViewPrivate *priv;
1563 double zoom;
1564
1565 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
1566
1567 priv = view->priv;
1568
1569 if (smooth) {
1570 zoom = priv->zoom * priv->zoom_multiplier;
1571 }
1572 else {
1573 int i;
1574 int index = -1;
1575
1576 for (i = 0; i < n_zoom_levels; i++) {
1577 if (preferred_zoom_levels [i] - priv->zoom
1578 > DOUBLE_EQUAL_MAX_DIFF1e-6) {
1579 index = i;
1580 break;
1581 }
1582 }
1583
1584 if (index == -1) {
1585 zoom = priv->zoom;
1586 }
1587 else {
1588 zoom = preferred_zoom_levels [i];
1589 }
1590 }
1591 set_zoom (view, zoom, FALSE(0), 0, 0);
1592
1593}
1594
1595void
1596eoc_scroll_view_zoom_out (EocScrollView *view, gboolean smooth)
1597{
1598 EocScrollViewPrivate *priv;
1599 double zoom;
1600
1601 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
1602
1603 priv = view->priv;
1604
1605 if (smooth) {
1606 zoom = priv->zoom / priv->zoom_multiplier;
1607 }
1608 else {
1609 int i;
1610 int index = -1;
1611
1612 for (i = n_zoom_levels - 1; i >= 0; i--) {
1613 if (priv->zoom - preferred_zoom_levels [i]
1614 > DOUBLE_EQUAL_MAX_DIFF1e-6) {
1615 index = i;
1616 break;
1617 }
1618 }
1619 if (index == -1) {
1620 zoom = priv->zoom;
1621 }
1622 else {
1623 zoom = preferred_zoom_levels [i];
1624 }
1625 }
1626 set_zoom (view, zoom, FALSE(0), 0, 0);
1627}
1628
1629void
1630eoc_scroll_view_zoom_fit (EocScrollView *view)
1631{
1632 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
1633
1634 set_zoom_fit (view);
1635 check_scrollbar_visibility (view, NULL((void*)0));
1636 ctk_widget_queue_draw (CTK_WIDGET (view->priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view->priv->display)), ((ctk_widget_get_type ())))
)))
);
1637}
1638
1639void
1640eoc_scroll_view_set_zoom (EocScrollView *view, double zoom)
1641{
1642 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
1643
1644 set_zoom (view, zoom, FALSE(0), 0, 0);
1645}
1646
1647double
1648eoc_scroll_view_get_zoom (EocScrollView *view)
1649{
1650 g_return_val_if_fail (EOC_IS_SCROLL_VIEW (view), 0.0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return (0.0); } } while (0)
;
1651
1652 return view->priv->zoom;
1653}
1654
1655gboolean
1656eoc_scroll_view_get_zoom_is_min (EocScrollView *view)
1657{
1658 g_return_val_if_fail (EOC_IS_SCROLL_VIEW (view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return ((0)); } } while (0)
;
1659
1660 set_minimum_zoom_factor (view);
1661
1662 return DOUBLE_EQUAL (view->priv->zoom, MIN_ZOOM_FACTOR)(fabs (view->priv->zoom - 0.02) < 1e-6) ||
1663 DOUBLE_EQUAL (view->priv->zoom, view->priv->min_zoom)(fabs (view->priv->zoom - view->priv->min_zoom) <
1e-6)
;
1664}
1665
1666gboolean
1667eoc_scroll_view_get_zoom_is_max (EocScrollView *view)
1668{
1669 g_return_val_if_fail (EOC_IS_SCROLL_VIEW (view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return ((0)); } } while (0)
;
1670
1671 return DOUBLE_EQUAL (view->priv->zoom, MAX_ZOOM_FACTOR)(fabs (view->priv->zoom - 20) < 1e-6);
1672}
1673
1674static void
1675display_next_frame_cb (EocImage *image, gint delay, gpointer data)
1676{
1677 EocScrollViewPrivate *priv;
1678 EocScrollView *view;
1679
1680 if (!EOC_IS_SCROLL_VIEW (data)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(data)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
1681 return;
1682
1683 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
1684 priv = view->priv;
1685
1686 update_pixbuf (view, eoc_image_get_pixbuf (image));
1687 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1688}
1689
1690void
1691eoc_scroll_view_set_image (EocScrollView *view, EocImage *image)
1692{
1693 EocScrollViewPrivate *priv;
1694
1695 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
1696
1697 priv = view->priv;
1698
1699 if (priv->image == image) {
1700 return;
1701 }
1702
1703 if (priv->image != NULL((void*)0)) {
1704 free_image_resources (view);
1705 }
1706 g_assert (priv->image == NULL)do { if (priv->image == ((void*)0)) ; else g_assertion_message_expr
("EOC", "eoc-scroll-view.c", 1706, ((const char*) (__func__)
), "priv->image == NULL"); } while (0)
;
1707 g_assert (priv->pixbuf == NULL)do { if (priv->pixbuf == ((void*)0)) ; else g_assertion_message_expr
("EOC", "eoc-scroll-view.c", 1707, ((const char*) (__func__)
), "priv->pixbuf == NULL"); } while (0)
;
1708
1709 if (image != NULL((void*)0)) {
1710 eoc_image_data_ref (image);
1711
1712 if (priv->pixbuf == NULL((void*)0)) {
1713 update_pixbuf (view, eoc_image_get_pixbuf (image));
1714 set_zoom_fit (view);
1715 check_scrollbar_visibility (view, NULL((void*)0));
1716 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1717
1718 }
1719
1720 priv->image_changed_id = g_signal_connect (image, "changed",g_signal_connect_data ((image), ("changed"), ((GCallback) image_changed_cb
), (view), ((void*)0), (GConnectFlags) 0)
1721 (GCallback) image_changed_cb, view)g_signal_connect_data ((image), ("changed"), ((GCallback) image_changed_cb
), (view), ((void*)0), (GConnectFlags) 0)
;
1722 if (eoc_image_is_animation (image) == TRUE(!(0)) ) {
1723 eoc_image_start_animation (image);
1724 priv->frame_changed_id = g_signal_connect (image, "next-frame",g_signal_connect_data ((image), ("next-frame"), ((GCallback) display_next_frame_cb
), (view), ((void*)0), (GConnectFlags) 0)
1725 (GCallback) display_next_frame_cb, view)g_signal_connect_data ((image), ("next-frame"), ((GCallback) display_next_frame_cb
), (view), ((void*)0), (GConnectFlags) 0)
;
1726 }
1727 }
1728
1729 priv->image = image;
1730
1731 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "image");
1732}
1733
1734/**
1735 * eoc_scroll_view_get_image:
1736 * @view: An #EocScrollView.
1737 *
1738 * Gets the the currently displayed #EocImage.
1739 *
1740 * Returns: (transfer full): An #EocImage.
1741 **/
1742EocImage*
1743eoc_scroll_view_get_image (EocScrollView *view)
1744{
1745 EocImage *img;
1746
1747 g_return_val_if_fail (EOC_IS_SCROLL_VIEW (view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return (((void*)0)); } } while
(0)
;
1748
1749 img = view->priv->image;
1750
1751 if (img != NULL((void*)0))
1752 g_object_ref (img)((__typeof__ (img)) (g_object_ref) (img));
1753
1754 return img;
1755}
1756
1757gboolean
1758eoc_scroll_view_scrollbars_visible (EocScrollView *view)
1759{
1760 if (!ctk_widget_get_visible (CTK_WIDGET (view->priv->hbar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view->priv->hbar)), ((ctk_widget_get_type ()))))))
) &&
1761 !ctk_widget_get_visible (CTK_WIDGET (view->priv->vbar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view->priv->vbar)), ((ctk_widget_get_type ()))))))
))
1762 return FALSE(0);
1763
1764 return TRUE(!(0));
1765}
1766
1767/*===================================
1768 object creation/freeing
1769 ---------------------------------*/
1770
1771static gboolean
1772sv_string_to_rgba_mapping (GValue *value,
1773 GVariant *variant,
1774 gpointer user_data)
1775{
1776 CdkRGBA color;
1777
1778 g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING), FALSE)do { if ((g_variant_is_of_type (variant, ((const GVariantType
*) "s")))) { } else { g_return_if_fail_warning ("EOC", ((const
char*) (__func__)), "g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)"
); return ((0)); } } while (0)
;
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
1779
1780 if (cdk_rgba_parse (&color, g_variant_get_string (variant, NULL((void*)0)))) {
1781 g_value_set_boxed (value, &color);
1782 return TRUE(!(0));
1783 }
1784
1785 return FALSE(0);
1786}
1787
1788static GVariant*
1789sv_rgba_to_string_mapping (const GValue *value,
1790 const GVariantType *expected_type,
1791 gpointer user_data)
1792{
1793 GVariant *variant = NULL((void*)0);
1794 CdkRGBA *color;
1795 gchar *hex_val;
1796
1797 g_return_val_if_fail (G_VALUE_TYPE (value) == CDK_TYPE_RGBA, NULL)do { if (((((GValue*) (value))->g_type) == (cdk_rgba_get_type
()))) { } else { g_return_if_fail_warning ("EOC", ((const char
*) (__func__)), "G_VALUE_TYPE (value) == CDK_TYPE_RGBA"); return
(((void*)0)); } } while (0)
;
1798 g_return_val_if_fail (g_variant_type_equal (expected_type, G_VARIANT_TYPE_STRING), NULL)do { if ((g_variant_type_equal (expected_type, ((const GVariantType
*) "s")))) { } else { g_return_if_fail_warning ("EOC", ((const
char*) (__func__)), "g_variant_type_equal (expected_type, G_VARIANT_TYPE_STRING)"
); return (((void*)0)); } } while (0)
;
1799
1800 color = g_value_get_boxed (value);
1801 hex_val = cdk_rgba_to_string(color);
1802 variant = g_variant_new_string (hex_val);
1803 g_free (hex_val);
1804
1805 return variant;
1806}
1807
1808static void
1809eoc_scroll_view_init (EocScrollView *view)
1810{
1811 GSettings *settings;
1812 EocScrollViewPrivate *priv;
1813
1814 priv = view->priv = eoc_scroll_view_get_instance_private (view);
1815 settings = g_settings_new (EOC_CONF_VIEW"org.cafe.eoc"".view");
1816
1817 priv->zoom = 1.0;
1818 priv->min_zoom = MIN_ZOOM_FACTOR0.02;
1819 priv->zoom_mode = ZOOM_MODE_FIT;
1820 priv->upscale = FALSE(0);
1821 priv->interp_type_in = CAIRO_FILTER_GOOD;
1822 priv->interp_type_out = CAIRO_FILTER_GOOD;
1823 priv->scroll_wheel_zoom = FALSE(0);
1824 priv->zoom_multiplier = IMAGE_VIEW_ZOOM_MULTIPLIER1.05;
1825 priv->image = NULL((void*)0);
1826 priv->pixbuf = NULL((void*)0);
1827 priv->surface = NULL((void*)0);
1828 priv->transp_style = EOC_TRANSP_BACKGROUND;
1829 g_warn_if_fail (cdk_rgba_parse(&priv->transp_color, CHECK_BLACK))do { if (cdk_rgba_parse(&priv->transp_color, "#000000"
)) ; else g_warn_message ("EOC", "eoc-scroll-view.c", 1829, (
(const char*) (__func__)), "cdk_rgba_parse(&priv->transp_color, CHECK_BLACK)"
); } while (0)
;
1830 priv->cursor = EOC_SCROLL_VIEW_CURSOR_NORMAL;
1831 priv->menu = NULL((void*)0);
1832 priv->background_color = NULL((void*)0);
1833
1834 priv->hadj = CTK_ADJUSTMENT (ctk_adjustment_new (0, 100, 0, 10, 10, 100))((((CtkAdjustment*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_adjustment_new (0, 100, 0, 10, 10, 100))), ((ctk_adjustment_get_type
()))))))
;
1835 g_signal_connect (priv->hadj, "value_changed",g_signal_connect_data ((priv->hadj), ("value_changed"), ((
(GCallback) (adjustment_changed_cb))), (view), ((void*)0), (GConnectFlags
) 0)
1836 G_CALLBACK (adjustment_changed_cb),g_signal_connect_data ((priv->hadj), ("value_changed"), ((
(GCallback) (adjustment_changed_cb))), (view), ((void*)0), (GConnectFlags
) 0)
1837 view)g_signal_connect_data ((priv->hadj), ("value_changed"), ((
(GCallback) (adjustment_changed_cb))), (view), ((void*)0), (GConnectFlags
) 0)
;
1838
1839 priv->hbar = ctk_scrollbar_new (CTK_ORIENTATION_HORIZONTAL, priv->hadj);
1840 priv->vadj = CTK_ADJUSTMENT (ctk_adjustment_new (0, 100, 0, 10, 10, 100))((((CtkAdjustment*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_adjustment_new (0, 100, 0, 10, 10, 100))), ((ctk_adjustment_get_type
()))))))
;
1841 g_signal_connect (priv->vadj, "value_changed",g_signal_connect_data ((priv->vadj), ("value_changed"), ((
(GCallback) (adjustment_changed_cb))), (view), ((void*)0), (GConnectFlags
) 0)
1842 G_CALLBACK (adjustment_changed_cb),g_signal_connect_data ((priv->vadj), ("value_changed"), ((
(GCallback) (adjustment_changed_cb))), (view), ((void*)0), (GConnectFlags
) 0)
1843 view)g_signal_connect_data ((priv->vadj), ("value_changed"), ((
(GCallback) (adjustment_changed_cb))), (view), ((void*)0), (GConnectFlags
) 0)
;
1844
1845 priv->vbar = ctk_scrollbar_new (CTK_ORIENTATION_VERTICAL, priv->vadj);
1846 priv->display = g_object_new (CTK_TYPE_DRAWING_AREA(ctk_drawing_area_get_type ()),
1847 "can-focus", TRUE(!(0)),
1848 NULL((void*)0));
1849 priv->scale = ctk_widget_get_scale_factor (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1850
1851 ctk_widget_add_events (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
,
1852 CDK_EXPOSURE_MASK
1853 | CDK_BUTTON_PRESS_MASK
1854 | CDK_BUTTON_RELEASE_MASK
1855 | CDK_POINTER_MOTION_MASK
1856 | CDK_POINTER_MOTION_HINT_MASK
1857 | CDK_SCROLL_MASK
1858 | CDK_KEY_PRESS_MASK);
1859 g_signal_connect (G_OBJECT (priv->display), "configure_event",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("configure_event"), (((GCallback) (display_size_change
))), (view), ((void*)0), (GConnectFlags) 0)
1860 G_CALLBACK (display_size_change), view)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("configure_event"), (((GCallback) (display_size_change
))), (view), ((void*)0), (GConnectFlags) 0)
;
1861 g_signal_connect (G_OBJECT (priv->display), "draw", G_CALLBACK (display_draw), view)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("draw"), (((GCallback) (display_draw))), (view
), ((void*)0), (GConnectFlags) 0)
;
1862 g_signal_connect (G_OBJECT (priv->display), "map_event",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("map_event"), (((GCallback) (display_map_event
))), (view), ((void*)0), (GConnectFlags) 0)
1863 G_CALLBACK (display_map_event), view)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("map_event"), (((GCallback) (display_map_event
))), (view), ((void*)0), (GConnectFlags) 0)
;
1864 g_signal_connect (G_OBJECT (priv->display), "button_press_event",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("button_press_event"), (((GCallback) (eoc_scroll_view_button_press_event
))), (view), ((void*)0), (GConnectFlags) 0)
1865 G_CALLBACK (eoc_scroll_view_button_press_event),g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("button_press_event"), (((GCallback) (eoc_scroll_view_button_press_event
))), (view), ((void*)0), (GConnectFlags) 0)
1866 view)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("button_press_event"), (((GCallback) (eoc_scroll_view_button_press_event
))), (view), ((void*)0), (GConnectFlags) 0)
;
1867 g_signal_connect (G_OBJECT (priv->display), "motion_notify_event",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("motion_notify_event"), (((GCallback) (eoc_scroll_view_motion_event
))), (view), ((void*)0), (GConnectFlags) 0)
1868 G_CALLBACK (eoc_scroll_view_motion_event), view)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("motion_notify_event"), (((GCallback) (eoc_scroll_view_motion_event
))), (view), ((void*)0), (GConnectFlags) 0)
;
1869 g_signal_connect (G_OBJECT (priv->display), "button_release_event",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("button_release_event"), (((GCallback) (eoc_scroll_view_button_release_event
))), (view), ((void*)0), (GConnectFlags) 0)
1870 G_CALLBACK (eoc_scroll_view_button_release_event),g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("button_release_event"), (((GCallback) (eoc_scroll_view_button_release_event
))), (view), ((void*)0), (GConnectFlags) 0)
1871 view)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("button_release_event"), (((GCallback) (eoc_scroll_view_button_release_event
))), (view), ((void*)0), (GConnectFlags) 0)
;
1872 g_signal_connect (G_OBJECT (priv->display), "scroll_event",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("scroll_event"), (((GCallback) (eoc_scroll_view_scroll_event
))), (view), ((void*)0), (GConnectFlags) 0)
1873 G_CALLBACK (eoc_scroll_view_scroll_event), view)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("scroll_event"), (((GCallback) (eoc_scroll_view_scroll_event
))), (view), ((void*)0), (GConnectFlags) 0)
;
1874 g_signal_connect (G_OBJECT (priv->display), "focus_in_event",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("focus_in_event"), (((GCallback) (eoc_scroll_view_focus_in_event
))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
1875 G_CALLBACK (eoc_scroll_view_focus_in_event), NULL)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("focus_in_event"), (((GCallback) (eoc_scroll_view_focus_in_event
))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
;
1876 g_signal_connect (G_OBJECT (priv->display), "focus_out_event",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("focus_out_event"), (((GCallback) (eoc_scroll_view_focus_out_event
))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
1877 G_CALLBACK (eoc_scroll_view_focus_out_event), NULL)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("focus_out_event"), (((GCallback) (eoc_scroll_view_focus_out_event
))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
;
1878
1879 g_signal_connect (G_OBJECT (view), "key_press_event",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((view)), (((GType) ((20) << (2)))))
)))), ("key_press_event"), (((GCallback) (display_key_press_event
))), (view), ((void*)0), (GConnectFlags) 0)
1880 G_CALLBACK (display_key_press_event), view)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((view)), (((GType) ((20) << (2)))))
)))), ("key_press_event"), (((GCallback) (display_key_press_event
))), (view), ((void*)0), (GConnectFlags) 0)
;
1881
1882 ctk_drag_source_set (priv->display, CDK_BUTTON1_MASK,
1883 target_table, G_N_ELEMENTS (target_table)(sizeof (target_table) / sizeof ((target_table)[0])),
1884 CDK_ACTION_COPY | CDK_ACTION_MOVE |
1885 CDK_ACTION_LINK | CDK_ACTION_ASK);
1886 g_signal_connect (G_OBJECT (priv->display), "drag-data-get",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("drag-data-get"), (((GCallback) (view_on_drag_data_get_cb
))), (view), ((void*)0), (GConnectFlags) 0)
1887 G_CALLBACK (view_on_drag_data_get_cb), view)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("drag-data-get"), (((GCallback) (view_on_drag_data_get_cb
))), (view), ((void*)0), (GConnectFlags) 0)
;
1888 g_signal_connect (G_OBJECT (priv->display), "drag-begin",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("drag-begin"), (((GCallback) (view_on_drag_begin_cb
))), (view), ((void*)0), (GConnectFlags) 0)
1889 G_CALLBACK (view_on_drag_begin_cb), view)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((priv->display)), (((GType) ((20) <<
(2))))))))), ("drag-begin"), (((GCallback) (view_on_drag_begin_cb
))), (view), ((void*)0), (GConnectFlags) 0)
;
1890
1891 ctk_grid_attach (CTK_GRID (view)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), ((ctk_grid_get_type ()))))))
, priv->display,
1892 0, 0, 1, 1);
1893 ctk_widget_set_hexpand (priv->display, TRUE(!(0)));
1894 ctk_widget_set_vexpand (priv->display, TRUE(!(0)));
1895 ctk_grid_attach (CTK_GRID (view)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), ((ctk_grid_get_type ()))))))
, priv->hbar,
1896 0, 1, 1, 1);
1897 ctk_widget_set_hexpand (priv->hbar, TRUE(!(0)));
1898 ctk_grid_attach (CTK_GRID (view)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), ((ctk_grid_get_type ()))))))
, priv->vbar,
1899 1, 0, 1, 1);
1900 ctk_widget_set_vexpand (priv->vbar, TRUE(!(0)));
1901
1902 g_settings_bind (settings, EOC_CONF_VIEW_USE_BG_COLOR"use-background-color", view,
1903 "use-background-color", G_SETTINGS_BIND_DEFAULT);
1904 g_settings_bind_with_mapping (settings, EOC_CONF_VIEW_BACKGROUND_COLOR"background-color",
1905 view, "background-color",
1906 G_SETTINGS_BIND_DEFAULT,
1907 sv_string_to_rgba_mapping,
1908 sv_rgba_to_string_mapping, NULL((void*)0), NULL((void*)0));
1909 g_settings_bind (settings, EOC_CONF_VIEW_EXTRAPOLATE"extrapolate", view,
1910 "antialiasing-in", G_SETTINGS_BIND_GET);
1911 g_settings_bind (settings, EOC_CONF_VIEW_INTERPOLATE"interpolate", view,
1912 "antialiasing-out", G_SETTINGS_BIND_GET);
1913 g_settings_bind_with_mapping (settings, EOC_CONF_VIEW_TRANS_COLOR"trans-color",
1914 view, "transparency-color",
1915 G_SETTINGS_BIND_GET,
1916 sv_string_to_rgba_mapping,
1917 sv_rgba_to_string_mapping, NULL((void*)0), NULL((void*)0));
1918 g_settings_bind (settings, EOC_CONF_VIEW_TRANSPARENCY"transparency", view,
1919 "transparency-style", G_SETTINGS_BIND_GET);
1920
1921 g_object_unref (settings);
1922
1923 priv->override_bg_color = NULL((void*)0);
1924 priv->background_surface = NULL((void*)0);
1925}
1926
1927static void
1928eoc_scroll_view_dispose (GObject *object)
1929{
1930 EocScrollView *view;
1931 EocScrollViewPrivate *priv;
1932
1933 g_return_if_fail (EOC_IS_SCROLL_VIEW (object))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (object)"); return; } } while (0)
;
1934
1935 view = EOC_SCROLL_VIEW (object)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((eoc_scroll_view_get_type ()))))))
;
1936 priv = view->priv;
1937
1938 _clear_hq_redraw_timeout (view);
1939
1940 if (priv->idle_id != 0) {
1941 g_source_remove (priv->idle_id);
1942 priv->idle_id = 0;
1943 }
1944
1945 if (priv->background_color != NULL((void*)0)) {
1946 cdk_rgba_free (priv->background_color);
1947 priv->background_color = NULL((void*)0);
1948 }
1949
1950 if (priv->override_bg_color != NULL((void*)0)) {
1951 cdk_rgba_free (priv->override_bg_color);
1952 priv->override_bg_color = NULL((void*)0);
1953 }
1954
1955 if (priv->background_surface != NULL((void*)0)) {
1956 cairo_surface_destroy (priv->background_surface);
1957 priv->background_surface = NULL((void*)0);
1958 }
1959
1960 free_image_resources (view);
1961
1962 G_OBJECT_CLASS (eoc_scroll_view_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((eoc_scroll_view_parent_class)), (((GType) ((20) <<
(2))))))))
->dispose (object);
1963}
1964
1965static void
1966eoc_scroll_view_get_property (GObject *object, guint property_id,
1967 GValue *value, GParamSpec *pspec)
1968{
1969 EocScrollView *view;
1970 EocScrollViewPrivate *priv;
1971
1972 g_return_if_fail (EOC_IS_SCROLL_VIEW (object))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (object)"); return; } } while (0)
;
1973
1974 view = EOC_SCROLL_VIEW (object)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((eoc_scroll_view_get_type ()))))))
;
1975 priv = view->priv;
1976
1977 switch (property_id) {
1978 case PROP_ANTIALIAS_IN:
1979 {
1980 gboolean filter = (priv->interp_type_in != CAIRO_FILTER_NEAREST);
1981 g_value_set_boolean (value, filter);
1982 break;
1983 }
1984 case PROP_ANTIALIAS_OUT:
1985 {
1986 gboolean filter = (priv->interp_type_out != CAIRO_FILTER_NEAREST);
1987 g_value_set_boolean (value, filter);
1988 break;
1989 }
1990 case PROP_USE_BG_COLOR:
1991 g_value_set_boolean (value, priv->use_bg_color);
1992 break;
1993 case PROP_BACKGROUND_COLOR:
1994 //FIXME: This doesn't really handle the NULL color.
1995 g_value_set_boxed (value, priv->background_color);
1996 break;
1997 case PROP_SCROLLWHEEL_ZOOM:
1998 g_value_set_boolean (value, priv->scroll_wheel_zoom);
1999 break;
2000 case PROP_TRANSPARENCY_STYLE:
2001 g_value_set_enum (value, priv->transp_style);
2002 break;
2003 case PROP_ZOOM_MULTIPLIER:
2004 g_value_set_double (value, priv->zoom_multiplier);
2005 break;
2006 case PROP_IMAGE:
2007 g_value_set_object (value, priv->image);
2008 break;
2009 default:
2010 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "eoc-scroll-view.c", 2010, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
2011 }
2012}
2013
2014static void
2015eoc_scroll_view_set_property (GObject *object, guint property_id,
2016 const GValue *value, GParamSpec *pspec)
2017{
2018 EocScrollView *view;
2019
2020 g_return_if_fail (EOC_IS_SCROLL_VIEW (object))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (object)"); return; } } while (0)
;
2021
2022 view = EOC_SCROLL_VIEW (object)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((eoc_scroll_view_get_type ()))))))
;
2023
2024 switch (property_id) {
2025 case PROP_ANTIALIAS_IN:
2026 eoc_scroll_view_set_antialiasing_in (view, g_value_get_boolean (value));
2027 break;
2028 case PROP_ANTIALIAS_OUT:
2029 eoc_scroll_view_set_antialiasing_out (view, g_value_get_boolean (value));
2030 break;
2031 case PROP_USE_BG_COLOR:
2032 eoc_scroll_view_set_use_bg_color (view, g_value_get_boolean (value));
2033 break;
2034 case PROP_BACKGROUND_COLOR:
2035 {
2036 const CdkRGBA *color = g_value_get_boxed (value);
2037 eoc_scroll_view_set_background_color (view, color);
2038 break;
2039 }
2040 case PROP_SCROLLWHEEL_ZOOM:
2041 eoc_scroll_view_set_scroll_wheel_zoom (view, g_value_get_boolean (value));
2042 break;
2043 case PROP_TRANSP_COLOR:
2044 eoc_scroll_view_set_transparency_color (view, g_value_get_boxed (value));
2045 break;
2046 case PROP_TRANSPARENCY_STYLE:
2047 eoc_scroll_view_set_transparency (view, g_value_get_enum (value));
2048 break;
2049 case PROP_ZOOM_MULTIPLIER:
2050 eoc_scroll_view_set_zoom_multiplier (view, g_value_get_double (value));
2051 break;
2052 case PROP_IMAGE:
2053 eoc_scroll_view_set_image (view, g_value_get_object (value));
2054 break;
2055 default:
2056 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "eoc-scroll-view.c", 2056, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
2057 }
2058}
2059
2060
2061static void
2062eoc_scroll_view_class_init (EocScrollViewClass *klass)
2063{
2064 GObjectClass *gobject_class;
2065 CtkWidgetClass *widget_class;
2066
2067 gobject_class = (GObjectClass*) klass;
2068 widget_class = (CtkWidgetClass*) klass;
2069
2070 gobject_class->dispose = eoc_scroll_view_dispose;
2071 gobject_class->set_property = eoc_scroll_view_set_property;
2072 gobject_class->get_property = eoc_scroll_view_get_property;
2073
2074 g_object_class_install_property (
2075 gobject_class, PROP_ANTIALIAS_IN,
2076 g_param_spec_boolean ("antialiasing-in", NULL((void*)0), NULL((void*)0), TRUE(!(0)),
2077 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2078
2079 g_object_class_install_property (
2080 gobject_class, PROP_ANTIALIAS_OUT,
2081 g_param_spec_boolean ("antialiasing-out", NULL((void*)0), NULL((void*)0), TRUE(!(0)),
2082 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2083
2084 /**
2085 * EocScrollView:background-color:
2086 *
2087 * This is the default background color used for painting the background
2088 * of the image view. If set to %NULL the color is determined by the
2089 * active CTK theme.
2090 */
2091 g_object_class_install_property (
2092 gobject_class, PROP_BACKGROUND_COLOR,
2093 g_param_spec_boxed ("background-color", NULL((void*)0), NULL((void*)0),
2094 CDK_TYPE_RGBA(cdk_rgba_get_type ()),
2095 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2096
2097 g_object_class_install_property (
2098 gobject_class, PROP_USE_BG_COLOR,
2099 g_param_spec_boolean ("use-background-color", NULL((void*)0), NULL((void*)0), FALSE(0),
2100 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2101
2102 /**
2103 * EocScrollView:zoom-multiplier:
2104 *
2105 * The current zoom factor is multiplied with this value + 1.0 when
2106 * scrolling with the scrollwheel to determine the next zoom factor.
2107 */
2108 g_object_class_install_property (
2109 gobject_class, PROP_ZOOM_MULTIPLIER,
2110 g_param_spec_double ("zoom-multiplier", NULL((void*)0), NULL((void*)0),
2111 -G_MAXDOUBLE1.7976931348623157e+308, G_MAXDOUBLE1.7976931348623157e+308 -1.0, 0.05,
2112 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2113
2114 /**
2115 * EocScrollView:scrollwheel-zoom:
2116 *
2117 * If %TRUE the scrollwheel will zoom the view, otherwise it will be
2118 * used for scrolling a zoomed image.
2119 */
2120 g_object_class_install_property (
2121 gobject_class, PROP_SCROLLWHEEL_ZOOM,
2122 g_param_spec_boolean ("scrollwheel-zoom", NULL((void*)0), NULL((void*)0), TRUE(!(0)),
2123 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2124
2125 /**
2126 * EocScrollView:image:
2127 *
2128 * This is the currently display #EocImage.
2129 */
2130 g_object_class_install_property (
2131 gobject_class, PROP_IMAGE,
2132 g_param_spec_object ("image", NULL((void*)0), NULL((void*)0), EOC_TYPE_IMAGE(eoc_image_get_type ()),
2133 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2134
2135 /**
2136 * EocScrollView:transparency-color:
2137 *
2138 * This is the color used to fill the transparent parts of an image
2139 * if :transparency-style is set to use a custom color.
2140 */
2141 g_object_class_install_property (
2142 gobject_class, PROP_TRANSP_COLOR,
2143 g_param_spec_boxed ("transparency-color", NULL((void*)0), NULL((void*)0),
2144 CDK_TYPE_RGBA(cdk_rgba_get_type ()),
2145 G_PARAM_WRITABLE | G_PARAM_STATIC_NAME));
2146
2147 /**
2148 * EocScrollView:transparency-style:
2149 *
2150 * Determines how to fill the shown image's transparent areas.
2151 */
2152 g_object_class_install_property (
2153 gobject_class, PROP_TRANSPARENCY_STYLE,
2154 g_param_spec_enum ("transparency-style", NULL((void*)0), NULL((void*)0),
2155 EOC_TYPE_TRANSPARENCY_STYLE(eoc_transparency_style_get_type()),
2156 EOC_TRANSP_CHECKED,
2157 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2158
2159 view_signals [SIGNAL_ZOOM_CHANGED] =
2160 g_signal_new ("zoom_changed",
2161 EOC_TYPE_SCROLL_VIEW(eoc_scroll_view_get_type ()),
2162 G_SIGNAL_RUN_LAST,
2163 G_STRUCT_OFFSET (EocScrollViewClass, zoom_changed)((glong) __builtin_offsetof(EocScrollViewClass, zoom_changed)
)
,
2164 NULL((void*)0), NULL((void*)0),
2165 eoc_marshal_VOID__DOUBLEg_cclosure_marshal_VOID__DOUBLE,
2166 G_TYPE_NONE((GType) ((1) << (2))), 1,
2167 G_TYPE_DOUBLE((GType) ((15) << (2))));
2168
2169 widget_class->size_allocate = eoc_scroll_view_size_allocate;
2170}
2171
2172static void
2173view_on_drag_begin_cb (CtkWidget *widget,
2174 CdkDragContext *context,
2175 gpointer user_data)
2176{
2177 EocScrollView *view;
2178 EocImage *image;
2179 GdkPixbuf *thumbnail;
2180 gint width, height;
2181
2182 view = EOC_SCROLL_VIEW (user_data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((eoc_scroll_view_get_type ()))))))
;
2183 image = view->priv->image;
2184
2185 thumbnail = eoc_image_get_thumbnail (image);
2186
2187 if (thumbnail) {
2188 width = gdk_pixbuf_get_width (thumbnail) / view->priv->scale;
2189 height = gdk_pixbuf_get_height (thumbnail) / view->priv->scale;
2190 ctk_drag_set_icon_pixbuf (context, thumbnail, width/2, height/2);
2191 g_object_unref (thumbnail);
2192 }
2193}
2194
2195static void
2196view_on_drag_data_get_cb (CtkWidget *widget,
2197 CdkDragContext *drag_context,
2198 CtkSelectionData *data,
2199 guint info,
2200 guint time,
2201 gpointer user_data)
2202{
2203 EocScrollView *view;
2204 EocImage *image;
2205 gchar *uris[2];
2206 GFile *file;
2207
2208 view = EOC_SCROLL_VIEW (user_data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((eoc_scroll_view_get_type ()))))))
;
2209
2210 image = view->priv->image;
2211
2212 file = eoc_image_get_file (image);
2213 uris[0] = g_file_get_uri (file);
2214 uris[1] = NULL((void*)0);
2215
2216 ctk_selection_data_set_uris (data, uris);
2217
2218 g_free (uris[0]);
2219 g_object_unref (file);
2220}
2221
2222CtkWidget*
2223eoc_scroll_view_new (void)
2224{
2225 CtkWidget *widget;
2226
2227 widget = g_object_new (EOC_TYPE_SCROLL_VIEW(eoc_scroll_view_get_type ()),
2228 "can-focus", TRUE(!(0)),
2229 "row-homogeneous", FALSE(0),
2230 "column-homogeneous", FALSE(0),
2231 NULL((void*)0));
2232
2233
2234 return widget;
2235}
2236
2237static gboolean
2238view_on_button_press_event_cb (CtkWidget *widget, CdkEventButton *event,
2239 gpointer user_data)
2240{
2241 EocScrollView *view = EOC_SCROLL_VIEW (widget)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((eoc_scroll_view_get_type ()))))))
;
2242
2243 /* Ignore double-clicks and triple-clicks */
2244 if (event->button == 3 && event->type == CDK_BUTTON_PRESS)
2245 {
2246 ctk_menu_popup_at_pointer (CTK_MENU (view->priv->menu)((((CtkMenu*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view->priv->menu)), ((ctk_menu_get_type ()))))))
,
2247 (const CdkEvent*) event);
2248
2249 return TRUE(!(0));
2250 }
2251
2252 return FALSE(0);
2253}
2254
2255void
2256eoc_scroll_view_set_popup (EocScrollView *view,
2257 CtkMenu *menu)
2258{
2259 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
2260 g_return_if_fail (view->priv->menu == NULL)do { if ((view->priv->menu == ((void*)0))) { } else { g_return_if_fail_warning
("EOC", ((const char*) (__func__)), "view->priv->menu == NULL"
); return; } } while (0)
;
2261
2262 view->priv->menu = g_object_ref (CTK_WIDGET (menu))((__typeof__ (((((CtkWidget*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((menu)), ((ctk_widget_get_type ()))))))))
(g_object_ref) (((((CtkWidget*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((menu)), ((ctk_widget_get_type ()))))))))
;
2263
2264 ctk_menu_attach_to_widget (CTK_MENU (view->priv->menu)((((CtkMenu*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view->priv->menu)), ((ctk_menu_get_type ()))))))
,
2265 CTK_WIDGET (view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), ((ctk_widget_get_type ()))))))
,
2266 NULL((void*)0));
2267
2268 g_signal_connect (G_OBJECT (view), "button_press_event",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((view)), (((GType) ((20) << (2)))))
)))), ("button_press_event"), (((GCallback) (view_on_button_press_event_cb
))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
2269 G_CALLBACK (view_on_button_press_event_cb), NULL)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((view)), (((GType) ((20) << (2)))))
)))), ("button_press_event"), (((GCallback) (view_on_button_press_event_cb
))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
;
2270}
2271
2272static gboolean
2273_eoc_cdk_rgba_equal0 (const CdkRGBA *a, const CdkRGBA *b)
2274{
2275 if (a == NULL((void*)0) || b == NULL((void*)0))
2276 return (a == b);
2277
2278 return cdk_rgba_equal (a, b);
2279}
2280
2281static gboolean
2282_eoc_replace_cdk_rgba (CdkRGBA **dest, const CdkRGBA *src)
2283{
2284 CdkRGBA *old = *dest;
2285
2286 if (_eoc_cdk_rgba_equal0 (old, src))
2287 return FALSE(0);
2288
2289 if (old != NULL((void*)0))
2290 cdk_rgba_free (old);
2291
2292 *dest = (src) ? cdk_rgba_copy (src) : NULL((void*)0);
2293
2294 return TRUE(!(0));
2295}
2296
2297static void
2298_eoc_scroll_view_update_bg_color (EocScrollView *view)
2299{
2300 EocScrollViewPrivate *priv = view->priv;
2301
2302 if (priv->transp_style == EOC_TRANSP_BACKGROUND
2303 && priv->background_surface != NULL((void*)0)) {
2304 /* Delete the SVG background to have it recreated with
2305 * the correct color during the next SVG redraw */
2306 cairo_surface_destroy (priv->background_surface);
2307 priv->background_surface = NULL((void*)0);
2308 }
2309
2310 ctk_widget_queue_draw (priv->display);
2311}
2312
2313void
2314eoc_scroll_view_set_background_color (EocScrollView *view,
2315 const CdkRGBA *color)
2316{
2317 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
2318
2319 if (_eoc_replace_cdk_rgba (&view->priv->background_color, color))
2320 _eoc_scroll_view_update_bg_color (view);
2321}
2322
2323void
2324eoc_scroll_view_override_bg_color (EocScrollView *view,
2325 const CdkRGBA *color)
2326{
2327 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
2328
2329 if (_eoc_replace_cdk_rgba (&view->priv->override_bg_color, color))
2330 _eoc_scroll_view_update_bg_color (view);
2331}
2332
2333void
2334eoc_scroll_view_set_use_bg_color (EocScrollView *view, gboolean use)
2335{
2336 EocScrollViewPrivate *priv;
2337
2338 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
2339
2340 priv = view->priv;
2341
2342 if (use != priv->use_bg_color) {
2343 priv->use_bg_color = use;
2344
2345 _eoc_scroll_view_update_bg_color (view);
2346
2347 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "use-background-color");
2348 }
2349}
2350
2351void
2352eoc_scroll_view_set_scroll_wheel_zoom (EocScrollView *view,
2353 gboolean scroll_wheel_zoom)
2354{
2355 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
2356
2357 if (view->priv->scroll_wheel_zoom != scroll_wheel_zoom) {
2358 view->priv->scroll_wheel_zoom = scroll_wheel_zoom;
2359 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "scrollwheel-zoom");
2360 }
2361}
2362
2363void
2364eoc_scroll_view_set_zoom_multiplier (EocScrollView *view,
2365 gdouble zoom_multiplier)
2366{
2367 g_return_if_fail (EOC_IS_SCROLL_VIEW (view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = ((eoc_scroll_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("EOC", ((const char*) (__func__
)), "EOC_IS_SCROLL_VIEW (view)"); return; } } while (0)
;
2368
2369 view->priv->zoom_multiplier = 1.0 + zoom_multiplier;
2370
2371 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "zoom-multiplier");
2372}