Bug Summary

File:src/eoc-scroll-view.c
Warning:line 1800, 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-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 -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib/llvm-19/lib/clang/19 -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/share/eoc" -D EOC_LOCALE_DIR="/usr/share/locale" -D EOC_PLUGIN_DIR="/usr/lib/eoc/plugins" -D LIBDIR="/usr/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/sysprof-6 -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/webp -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-2.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/exempi-2.0 -I /usr/include/librsvg-2.0 -I /usr/include/libxml2 -D PIC -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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.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/2025-06-29-115311-31284-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 GType 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_pointer (
&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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (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 ctk_widget_queue_resize (CTK_WIDGET (view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), ((ctk_widget_get_type ()))))))
);
967
968 return TRUE(!(0));
969 }
970 default:
971 break;
972 }
973
974 return FALSE(0);
975}
976
977/* Button release event handler for the image view */
978static gboolean
979eoc_scroll_view_button_release_event (CtkWidget *widget, CdkEventButton *event, gpointer data)
980{
981 EocScrollView *view;
982 EocScrollViewPrivate *priv;
983
984 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
985 priv = view->priv;
986
987 if (!priv->dragging)
988 return FALSE(0);
989
990 switch (event->button) {
991 case 1:
992 case 2:
993 drag_to (view, event->x, event->y);
994 priv->dragging = FALSE(0);
995
996 eoc_scroll_view_set_cursor (view, EOC_SCROLL_VIEW_CURSOR_NORMAL);
997 break;
998
999 default:
1000 break;
1001 }
1002
1003 return TRUE(!(0));
1004}
1005
1006/* Scroll event handler for the image view. We zoom with an event without
1007 * modifiers rather than scroll; we use the Shift modifier to scroll.
1008 * Rationale: images are not primarily vertical, and in EOC you scan scroll by
1009 * dragging the image with button 1 anyways.
1010 */
1011static gboolean
1012eoc_scroll_view_scroll_event (CtkWidget *widget, CdkEventScroll *event, gpointer data)
1013{
1014 EocScrollView *view;
1015 EocScrollViewPrivate *priv;
1016 double zoom_factor;
1017 int xofs, yofs;
1018
1019 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
1020 priv = view->priv;
1021
1022 /* Compute zoom factor and scrolling offsets; we'll only use either of them */
1023 /* same as in ctkscrolledwindow.c */
1024 xofs = ctk_adjustment_get_page_increment (priv->hadj) / 2;
1025 yofs = ctk_adjustment_get_page_increment (priv->vadj) / 2;
1026
1027 switch (event->direction) {
1028 case CDK_SCROLL_UP:
1029 zoom_factor = priv->zoom_multiplier;
1030 xofs = 0;
1031 yofs = -yofs;
1032 break;
1033
1034 case CDK_SCROLL_LEFT:
1035 zoom_factor = 1.0 / priv->zoom_multiplier;
1036 xofs = -xofs;
1037 yofs = 0;
1038 break;
1039
1040 case CDK_SCROLL_DOWN:
1041 zoom_factor = 1.0 / priv->zoom_multiplier;
1042 xofs = 0;
1043 yofs = yofs;
1044 break;
1045
1046 case CDK_SCROLL_RIGHT:
1047 zoom_factor = priv->zoom_multiplier;
1048 xofs = xofs;
1049 yofs = 0;
1050 break;
1051
1052 default:
1053 g_assert_not_reached ()do { g_assertion_message_expr ("EOC", "eoc-scroll-view.c", 1053
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1054 return FALSE(0);
1055 }
1056
1057 if (priv->scroll_wheel_zoom) {
1058 if (event->state & CDK_SHIFT_MASK)
1059 scroll_by (view, yofs, xofs);
1060 else if (event->state & CDK_CONTROL_MASK)
1061 scroll_by (view, xofs, yofs);
1062 else
1063 set_zoom (view, priv->zoom * zoom_factor,
1064 TRUE(!(0)), event->x, event->y);
1065 } else {
1066 if (event->state & CDK_SHIFT_MASK)
1067 scroll_by (view, yofs, xofs);
1068 else if (event->state & CDK_CONTROL_MASK)
1069 set_zoom (view, priv->zoom * zoom_factor,
1070 TRUE(!(0)), event->x, event->y);
1071 else
1072 scroll_by (view, xofs, yofs);
1073 }
1074
1075 return TRUE(!(0));
1076}
1077
1078/* Motion event handler for the image view */
1079static gboolean
1080eoc_scroll_view_motion_event (CtkWidget *widget, CdkEventMotion *event, gpointer data)
1081{
1082 EocScrollView *view;
1083 EocScrollViewPrivate *priv;
1084 gint x, y;
1085 CdkModifierType mods;
1086
1087 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
1088 priv = view->priv;
1089
1090 if (!priv->dragging)
1091 return FALSE(0);
1092
1093 if (event->is_hint)
1094 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);
1095 else {
1096 x = event->x;
1097 y = event->y;
1098 }
1099
1100 drag_to (view, x, y);
1101 return TRUE(!(0));
1102}
1103
1104static void
1105display_map_event (CtkWidget *widget, CdkEvent *event, gpointer data)
1106{
1107 EocScrollView *view;
1108 EocScrollViewPrivate *priv;
1109
1110 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
1111 priv = view->priv;
1112
1113 eoc_debug (DEBUG_WINDOWEOC_DEBUG_WINDOW, "eoc-scroll-view.c", 1113, ((const char*) (
__func__))
);
1114
1115 set_zoom_fit (view);
1116 check_scrollbar_visibility (view, NULL((void*)0));
1117 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1118}
1119
1120static void
1121eoc_scroll_view_size_allocate (CtkWidget *widget, CtkAllocation *alloc)
1122{
1123 EocScrollView *view;
1124
1125 view = EOC_SCROLL_VIEW (widget)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((eoc_scroll_view_get_type ()))))))
;
1126 check_scrollbar_visibility (view, alloc);
1127
1128 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
1129 ,alloc);
1130}
1131
1132static void
1133display_size_change (CtkWidget *widget, CdkEventConfigure *event, gpointer data)
1134{
1135 EocScrollView *view;
1136 EocScrollViewPrivate *priv;
1137
1138 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
1139 priv = view->priv;
1140
1141 if (priv->zoom_mode == ZOOM_MODE_FIT) {
1142 CtkAllocation alloc;
1143
1144 alloc.width = event->width;
1145 alloc.height = event->height;
1146
1147 set_zoom_fit (view);
1148 check_scrollbar_visibility (view, &alloc);
1149 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1150 } else {
1151 int scaled_width, scaled_height;
1152 int x_offset = 0;
1153 int y_offset = 0;
1154
1155 compute_scaled_size (view, priv->zoom, &scaled_width, &scaled_height);
1156
1157 if (priv->xofs + event->width > scaled_width)
1158 x_offset = scaled_width - event->width - priv->xofs;
1159
1160 if (priv->yofs + event->height > scaled_height)
1161 y_offset = scaled_height - event->height - priv->yofs;
1162
1163 scroll_by (view, x_offset, y_offset);
1164 }
1165
1166 update_scrollbar_values (view);
1167}
1168
1169
1170static gboolean
1171eoc_scroll_view_focus_in_event (CtkWidget *widget,
1172 CdkEventFocus *event,
1173 gpointer data)
1174{
1175 g_signal_stop_emission_by_name (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
, "focus_in_event");
1176 return FALSE(0);
1177}
1178
1179static gboolean
1180eoc_scroll_view_focus_out_event (CtkWidget *widget,
1181 CdkEventFocus *event,
1182 gpointer data)
1183{
1184 g_signal_stop_emission_by_name (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
, "focus_out_event");
1185 return FALSE(0);
1186}
1187
1188static gboolean _hq_redraw_cb (gpointer user_data)
1189{
1190 EocScrollViewPrivate *priv = EOC_SCROLL_VIEW (user_data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((eoc_scroll_view_get_type ()))))))
->priv;
1191
1192 priv->force_unfiltered = FALSE(0);
1193 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1194
1195 priv->hq_redraw_timeout_source = NULL((void*)0);
1196 return G_SOURCE_REMOVE(0);
1197}
1198
1199static void
1200_clear_hq_redraw_timeout (EocScrollView *view)
1201{
1202 EocScrollViewPrivate *priv = view->priv;
1203
1204 if (priv->hq_redraw_timeout_source != NULL((void*)0)) {
1205 g_source_unref (priv->hq_redraw_timeout_source);
1206 g_source_destroy (priv->hq_redraw_timeout_source);
1207 }
1208
1209 priv->hq_redraw_timeout_source = NULL((void*)0);
1210}
1211
1212static void
1213_set_hq_redraw_timeout (EocScrollView *view)
1214{
1215 GSource *source;
1216
1217 _clear_hq_redraw_timeout (view);
1218
1219 source = g_timeout_source_new (200);
1220 g_source_set_callback (source, &_hq_redraw_cb, view, NULL((void*)0));
1221
1222 g_source_attach (source, NULL((void*)0));
1223
1224 view->priv->hq_redraw_timeout_source = source;
1225}
1226
1227static gboolean
1228display_draw (CtkWidget *widget, cairo_t *cr, gpointer data)
1229{
1230 const CdkRGBA *background_color = NULL((void*)0);
1231 EocScrollView *view;
1232 EocScrollViewPrivate *priv;
1233 CtkAllocation allocation;
1234 int scaled_width, scaled_height;
1235 int xofs, yofs;
1236
1237 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)
;
1238 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)
;
1239
1240 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
1241
1242 priv = view->priv;
1243
1244 if (priv->pixbuf == NULL((void*)0))
1245 return TRUE(!(0));
1246
1247 compute_scaled_size (view, priv->zoom, &scaled_width, &scaled_height);
1248
1249 ctk_widget_get_allocation (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
, &allocation);
1250
1251 /* Compute image offsets with respect to the window */
1252
1253 if (scaled_width <= allocation.width)
1254 xofs = (allocation.width - scaled_width) / 2;
1255 else
1256 xofs = -priv->xofs;
1257
1258 if (scaled_height <= allocation.height)
1259 yofs = (allocation.height - scaled_height) / 2;
1260 else
1261 yofs = -priv->yofs;
1262
1263 eoc_debug_message (DEBUG_WINDOWEOC_DEBUG_WINDOW, "eoc-scroll-view.c", 1263, ((const char*) (
__func__))
, "zoom %.2f, xofs: %i, yofs: %i scaled w: %i h: %i\n",
1264 priv->zoom, xofs, yofs, scaled_width, scaled_height);
1265
1266 /* Paint the background */
1267 cairo_rectangle (cr, 0, 0, allocation.width, allocation.height);
1268 if (priv->transp_style != EOC_TRANSP_BACKGROUND)
1269 cairo_rectangle (cr, MAX (0, xofs)(((0) > (xofs)) ? (0) : (xofs)), MAX (0, yofs)(((0) > (yofs)) ? (0) : (yofs)),
1270 scaled_width, scaled_height);
1271 if (priv->override_bg_color != NULL((void*)0))
1272 background_color = priv->override_bg_color;
1273 else if (priv->use_bg_color)
1274 background_color = priv->background_color;
1275 if (background_color != NULL((void*)0))
1276 cairo_set_source_rgba (cr,
1277 background_color->red,
1278 background_color->green,
1279 background_color->blue,
1280 background_color->alpha);
1281 else
1282 cairo_set_source (cr, cdk_window_get_background_pattern (ctk_widget_get_window (priv->display)));
1283 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
1284 cairo_fill (cr);
1285
1286 if (gdk_pixbuf_get_has_alpha (priv->pixbuf)) {
1287 if (priv->background_surface == NULL((void*)0)) {
1288 priv->background_surface = create_background_surface (view);
1289 }
1290 cairo_set_source_surface (cr, priv->background_surface, xofs, yofs);
1291 cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
1292 cairo_rectangle (cr, xofs, yofs, scaled_width, scaled_height);
1293 cairo_fill (cr);
1294 }
1295
1296 /* Make sure the image is only drawn as large as needed.
1297 * This is especially necessary for SVGs where there might
1298 * be more image data available outside the image boundaries.
1299 */
1300 cairo_rectangle (cr, xofs, yofs, scaled_width, scaled_height);
1301 cairo_clip (cr);
1302
1303#ifdef HAVE_RSVG1
1304 if (eoc_image_is_svg (view->priv->image)) {
1305 cairo_matrix_t matrix, translate, scale, original;
1306 EocTransform *transform = eoc_image_get_transform (priv->image);
1307 cairo_matrix_init_identity (&matrix);
1308 if (transform) {
1309 cairo_matrix_t affine;
1310 double image_offset_x = 0., image_offset_y = 0.;
1311
1312 eoc_transform_get_affine (transform, &affine);
1313 cairo_matrix_multiply (&matrix, &affine, &matrix);
1314
1315 switch (eoc_transform_get_transform_type (transform)) {
1316 case EOC_TRANSFORM_ROT_90:
1317 case EOC_TRANSFORM_FLIP_HORIZONTAL:
1318 image_offset_x = (double) gdk_pixbuf_get_width (priv->pixbuf);
1319 break;
1320 case EOC_TRANSFORM_ROT_270:
1321 case EOC_TRANSFORM_FLIP_VERTICAL:
1322 image_offset_y = (double) gdk_pixbuf_get_height (priv->pixbuf);
1323 break;
1324 case EOC_TRANSFORM_ROT_180:
1325 case EOC_TRANSFORM_TRANSPOSE:
1326 case EOC_TRANSFORM_TRANSVERSE:
1327 image_offset_x = (double) gdk_pixbuf_get_width (priv->pixbuf);
1328 image_offset_y = (double) gdk_pixbuf_get_height (priv->pixbuf);
1329 break;
1330 case EOC_TRANSFORM_NONE:
1331 default:
1332 break;
1333 }
1334 cairo_matrix_init_translate (&translate, image_offset_x, image_offset_y);
1335 cairo_matrix_multiply (&matrix, &matrix, &translate);
1336 }
1337 /* Zoom factor for SVGs is already scaled, so scale back to application pixels. */
1338 cairo_matrix_init_scale (&scale, priv->zoom / priv->scale, priv->zoom / priv->scale);
1339 cairo_matrix_multiply (&matrix, &matrix, &scale);
1340 cairo_matrix_init_translate (&translate, xofs, yofs);
1341 cairo_matrix_multiply (&matrix, &matrix, &translate);
1342
1343 cairo_get_matrix (cr, &original);
1344 cairo_matrix_multiply (&matrix, &matrix, &original);
1345 cairo_set_matrix (cr, &matrix);
1346
1347 rsvg_handle_render_cairo (eoc_image_get_svg (priv->image), cr);
1348
1349 } else
1350#endif /* HAVE_RSVG */
1351 {
1352 cairo_filter_t interp_type;
1353
1354 if(!DOUBLE_EQUAL(priv->zoom, 1.0)(fabs (priv->zoom - 1.0) < 1e-6) && priv->force_unfiltered)
1355 {
1356 interp_type = CAIRO_FILTER_NEAREST;
1357 _set_hq_redraw_timeout(view);
1358 }
1359 else
1360 {
1361 if (is_zoomed_in (view))
1362 interp_type = priv->interp_type_in;
1363 else
1364 interp_type = priv->interp_type_out;
1365
1366 _clear_hq_redraw_timeout (view);
1367 priv->force_unfiltered = TRUE(!(0));
1368 }
1369 cairo_scale (cr, priv->zoom, priv->zoom);
1370 cairo_set_source_surface (cr, priv->surface, xofs/priv->zoom, yofs/priv->zoom);
1371 cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_PAD);
1372 if (is_zoomed_in (view) || is_zoomed_out (view))
1373 cairo_pattern_set_filter (cairo_get_source (cr), interp_type);
1374
1375 cairo_paint (cr);
1376 }
1377
1378 return TRUE(!(0));
1379}
1380
1381
1382/*==================================
1383
1384 image loading callbacks
1385
1386 -----------------------------------*/
1387
1388/* Use when the pixbuf in the view is changed, to keep a
1389 reference to it and create its cairo surface. */
1390static void
1391update_pixbuf (EocScrollView *view, GdkPixbuf *pixbuf)
1392{
1393 EocScrollViewPrivate *priv;
1394
1395 priv = view->priv;
1396
1397 if (priv->pixbuf != NULL((void*)0)) {
1398 g_object_unref (priv->pixbuf);
1399 priv->pixbuf = NULL((void*)0);
1400 }
1401
1402 priv->pixbuf = pixbuf;
1403
1404 if (priv->surface) {
1405 cairo_surface_destroy (priv->surface);
1406 }
1407 priv->surface = create_surface_from_pixbuf (view, priv->pixbuf);
1408}
1409
1410static void
1411image_changed_cb (EocImage *img, gpointer data)
1412{
1413 EocScrollViewPrivate *priv;
1414
1415 priv = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
->priv;
1416
1417 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));
1418
1419 set_zoom_fit (EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
);
1420 check_scrollbar_visibility (EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
, NULL((void*)0));
1421
1422 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1423}
1424
1425/*===================================
1426 public API
1427 ---------------------------------*/
1428
1429void
1430eoc_scroll_view_hide_cursor (EocScrollView *view)
1431{
1432 eoc_scroll_view_set_cursor (view, EOC_SCROLL_VIEW_CURSOR_HIDDEN);
1433}
1434
1435void
1436eoc_scroll_view_show_cursor (EocScrollView *view)
1437{
1438 eoc_scroll_view_set_cursor (view, EOC_SCROLL_VIEW_CURSOR_NORMAL);
1439}
1440
1441/* general properties */
1442void
1443eoc_scroll_view_set_zoom_upscale (EocScrollView *view, gboolean upscale)
1444{
1445 EocScrollViewPrivate *priv;
1446
1447 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)
;
1448
1449 priv = view->priv;
1450
1451 if (priv->upscale != upscale) {
1452 priv->upscale = upscale;
1453
1454 if (priv->zoom_mode == ZOOM_MODE_FIT) {
1455 set_zoom_fit (view);
1456 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1457 }
1458 }
1459}
1460
1461void
1462eoc_scroll_view_set_antialiasing_in (EocScrollView *view, gboolean state)
1463{
1464 EocScrollViewPrivate *priv;
1465 cairo_filter_t new_interp_type;
1466
1467 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)
;
1468
1469 priv = view->priv;
1470
1471 new_interp_type = state ? CAIRO_FILTER_GOOD : CAIRO_FILTER_NEAREST;
1472
1473 if (priv->interp_type_in != new_interp_type) {
1474 priv->interp_type_in = new_interp_type;
1475 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1476 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "antialiasing-in");
1477 }
1478}
1479
1480void
1481eoc_scroll_view_set_antialiasing_out (EocScrollView *view, gboolean state)
1482{
1483 EocScrollViewPrivate *priv;
1484 cairo_filter_t new_interp_type;
1485
1486 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)
;
1487
1488 priv = view->priv;
1489
1490 new_interp_type = state ? CAIRO_FILTER_GOOD : CAIRO_FILTER_NEAREST;
1491
1492 if (priv->interp_type_out != new_interp_type) {
1493 priv->interp_type_out = new_interp_type;
1494 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1495 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "antialiasing-out");
1496
1497 }
1498}
1499
1500static void
1501_transp_background_changed (EocScrollView *view)
1502{
1503 EocScrollViewPrivate *priv = view->priv;
1504
1505 if (priv->pixbuf != NULL((void*)0) && gdk_pixbuf_get_has_alpha (priv->pixbuf)) {
1506 if (priv->background_surface) {
1507 cairo_surface_destroy (priv->background_surface);
1508 /* Will be recreated if needed during redraw */
1509 priv->background_surface = NULL((void*)0);
1510 }
1511 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1512 }
1513
1514}
1515
1516void
1517eoc_scroll_view_set_transparency_color (EocScrollView *view, CdkRGBA *color)
1518{
1519 EocScrollViewPrivate *priv;
1520
1521 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)
;
1522
1523 priv = view->priv;
1524
1525 if (!_eoc_cdk_rgba_equal0 (&priv->transp_color, color)) {
1526 priv->transp_color = *color;
1527 if (priv->transp_style == EOC_TRANSP_COLOR)
1528 _transp_background_changed (view);
1529
1530 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "transparency-color");
1531 }
1532}
1533
1534void
1535eoc_scroll_view_set_transparency (EocScrollView *view,
1536 EocTransparencyStyle style)
1537{
1538 EocScrollViewPrivate *priv;
1539
1540 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)
;
1541
1542 priv = view->priv;
1543
1544 if (priv->transp_style != style) {
1545 priv->transp_style = style;
1546 _transp_background_changed (view);
1547 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "transparency-style");
1548 }
1549}
1550
1551/* zoom api */
1552
1553static double preferred_zoom_levels[] = {
1554 1.0 / 100, 1.0 / 50, 1.0 / 20,
1555 1.0 / 10.0, 1.0 / 5.0, 1.0 / 3.0, 1.0 / 2.0, 1.0 / 1.5,
1556 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0,
1557 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0
1558};
1559static const gint n_zoom_levels = (sizeof (preferred_zoom_levels) / sizeof (double));
1560
1561void
1562eoc_scroll_view_zoom_in (EocScrollView *view, gboolean smooth)
1563{
1564 EocScrollViewPrivate *priv;
1565 double zoom;
1566
1567 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)
;
1568
1569 priv = view->priv;
1570
1571 if (smooth) {
1572 zoom = priv->zoom * priv->zoom_multiplier;
1573 }
1574 else {
1575 int i;
1576 int index = -1;
1577
1578 for (i = 0; i < n_zoom_levels; i++) {
1579 if (preferred_zoom_levels [i] - priv->zoom
1580 > DOUBLE_EQUAL_MAX_DIFF1e-6) {
1581 index = i;
1582 break;
1583 }
1584 }
1585
1586 if (index == -1) {
1587 zoom = priv->zoom;
1588 }
1589 else {
1590 zoom = preferred_zoom_levels [i];
1591 }
1592 }
1593 set_zoom (view, zoom, FALSE(0), 0, 0);
1594
1595}
1596
1597void
1598eoc_scroll_view_zoom_out (EocScrollView *view, gboolean smooth)
1599{
1600 EocScrollViewPrivate *priv;
1601 double zoom;
1602
1603 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)
;
1604
1605 priv = view->priv;
1606
1607 if (smooth) {
1608 zoom = priv->zoom / priv->zoom_multiplier;
1609 }
1610 else {
1611 int i;
1612 int index = -1;
1613
1614 for (i = n_zoom_levels - 1; i >= 0; i--) {
1615 if (priv->zoom - preferred_zoom_levels [i]
1616 > DOUBLE_EQUAL_MAX_DIFF1e-6) {
1617 index = i;
1618 break;
1619 }
1620 }
1621 if (index == -1) {
1622 zoom = priv->zoom;
1623 }
1624 else {
1625 zoom = preferred_zoom_levels [i];
1626 }
1627 }
1628 set_zoom (view, zoom, FALSE(0), 0, 0);
1629}
1630
1631void
1632eoc_scroll_view_zoom_fit (EocScrollView *view)
1633{
1634 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)
;
1635
1636 set_zoom_fit (view);
1637 check_scrollbar_visibility (view, NULL((void*)0));
1638 ctk_widget_queue_draw (CTK_WIDGET (view->priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view->priv->display)), ((ctk_widget_get_type ())))
)))
);
1639}
1640
1641void
1642eoc_scroll_view_set_zoom (EocScrollView *view, double zoom)
1643{
1644 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)
;
1645
1646 set_zoom (view, zoom, FALSE(0), 0, 0);
1647}
1648
1649double
1650eoc_scroll_view_get_zoom (EocScrollView *view)
1651{
1652 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)
;
1653
1654 return view->priv->zoom;
1655}
1656
1657gboolean
1658eoc_scroll_view_get_zoom_is_min (EocScrollView *view)
1659{
1660 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)
;
1661
1662 set_minimum_zoom_factor (view);
1663
1664 return DOUBLE_EQUAL (view->priv->zoom, MIN_ZOOM_FACTOR)(fabs (view->priv->zoom - 0.02) < 1e-6) ||
1665 DOUBLE_EQUAL (view->priv->zoom, view->priv->min_zoom)(fabs (view->priv->zoom - view->priv->min_zoom) <
1e-6)
;
1666}
1667
1668gboolean
1669eoc_scroll_view_get_zoom_is_max (EocScrollView *view)
1670{
1671 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)
;
1672
1673 return DOUBLE_EQUAL (view->priv->zoom, MAX_ZOOM_FACTOR)(fabs (view->priv->zoom - 20) < 1e-6);
1674}
1675
1676static void
1677display_next_frame_cb (EocImage *image, gint delay, gpointer data)
1678{
1679 EocScrollViewPrivate *priv;
1680 EocScrollView *view;
1681
1682 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; }))))
)
1683 return;
1684
1685 view = EOC_SCROLL_VIEW (data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((eoc_scroll_view_get_type ()))))))
;
1686 priv = view->priv;
1687
1688 update_pixbuf (view, eoc_image_get_pixbuf (image));
1689 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1690}
1691
1692void
1693eoc_scroll_view_set_image (EocScrollView *view, EocImage *image)
1694{
1695 EocScrollViewPrivate *priv;
1696
1697 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)
;
1698
1699 priv = view->priv;
1700
1701 if (priv->image == image) {
1702 return;
1703 }
1704
1705 if (priv->image != NULL((void*)0)) {
1706 free_image_resources (view);
1707 }
1708 g_assert (priv->image == NULL)do { if (priv->image == ((void*)0)) ; else g_assertion_message_expr
("EOC", "eoc-scroll-view.c", 1708, ((const char*) (__func__)
), "priv->image == NULL"); } while (0)
;
1709 g_assert (priv->pixbuf == NULL)do { if (priv->pixbuf == ((void*)0)) ; else g_assertion_message_expr
("EOC", "eoc-scroll-view.c", 1709, ((const char*) (__func__)
), "priv->pixbuf == NULL"); } while (0)
;
1710
1711 if (image != NULL((void*)0)) {
1712 eoc_image_data_ref (image);
1713
1714 if (priv->pixbuf == NULL((void*)0)) {
1715 update_pixbuf (view, eoc_image_get_pixbuf (image));
1716 set_zoom_fit (view);
1717 check_scrollbar_visibility (view, NULL((void*)0));
1718 ctk_widget_queue_draw (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
);
1719
1720 }
1721
1722 priv->image_changed_id = g_signal_connect (image, "changed",g_signal_connect_data ((image), ("changed"), ((GCallback) image_changed_cb
), (view), ((void*)0), (GConnectFlags) 0)
1723 (GCallback) image_changed_cb, view)g_signal_connect_data ((image), ("changed"), ((GCallback) image_changed_cb
), (view), ((void*)0), (GConnectFlags) 0)
;
1724 if (eoc_image_is_animation (image) == TRUE(!(0)) ) {
1725 eoc_image_start_animation (image);
1726 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)
1727 (GCallback) display_next_frame_cb, view)g_signal_connect_data ((image), ("next-frame"), ((GCallback) display_next_frame_cb
), (view), ((void*)0), (GConnectFlags) 0)
;
1728 }
1729 }
1730
1731 priv->image = image;
1732
1733 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "image");
1734}
1735
1736/**
1737 * eoc_scroll_view_get_image:
1738 * @view: An #EocScrollView.
1739 *
1740 * Gets the the currently displayed #EocImage.
1741 *
1742 * Returns: (transfer full): An #EocImage.
1743 **/
1744EocImage*
1745eoc_scroll_view_get_image (EocScrollView *view)
1746{
1747 EocImage *img;
1748
1749 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)
;
1750
1751 img = view->priv->image;
1752
1753 if (img != NULL((void*)0))
1754 g_object_ref (img)((__typeof__ (img)) (g_object_ref) (img));
1755
1756 return img;
1757}
1758
1759gboolean
1760eoc_scroll_view_scrollbars_visible (EocScrollView *view)
1761{
1762 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 ()))))))
) &&
1763 !ctk_widget_get_visible (CTK_WIDGET (view->priv->vbar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view->priv->vbar)), ((ctk_widget_get_type ()))))))
))
1764 return FALSE(0);
1765
1766 return TRUE(!(0));
1767}
1768
1769/*===================================
1770 object creation/freeing
1771 ---------------------------------*/
1772
1773static gboolean
1774sv_string_to_rgba_mapping (GValue *value,
1775 GVariant *variant,
1776 gpointer user_data)
1777{
1778 CdkRGBA color;
1779
1780 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)
;
1781
1782 if (cdk_rgba_parse (&color, g_variant_get_string (variant, NULL((void*)0)))) {
1783 g_value_set_boxed (value, &color);
1784 return TRUE(!(0));
1785 }
1786
1787 return FALSE(0);
1788}
1789
1790static GVariant*
1791sv_rgba_to_string_mapping (const GValue *value,
1792 const GVariantType *expected_type,
1793 gpointer user_data)
1794{
1795 GVariant *variant = NULL((void*)0);
1796 CdkRGBA *color;
1797 gchar *hex_val;
1798
1799 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)
;
1800 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)
;
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
1801
1802 color = g_value_get_boxed (value);
1803 hex_val = cdk_rgba_to_string(color);
1804 variant = g_variant_new_string (hex_val);
1805 g_free (hex_val);
1806
1807 return variant;
1808}
1809
1810static void
1811eoc_scroll_view_init (EocScrollView *view)
1812{
1813 GSettings *settings;
1814 EocScrollViewPrivate *priv;
1815
1816 priv = view->priv = eoc_scroll_view_get_instance_private (view);
1817 settings = g_settings_new (EOC_CONF_VIEW"org.cafe.eoc"".view");
1818
1819 priv->zoom = 1.0;
1820 priv->min_zoom = MIN_ZOOM_FACTOR0.02;
1821 priv->zoom_mode = ZOOM_MODE_FIT;
1822 priv->upscale = FALSE(0);
1823 priv->interp_type_in = CAIRO_FILTER_GOOD;
1824 priv->interp_type_out = CAIRO_FILTER_GOOD;
1825 priv->scroll_wheel_zoom = FALSE(0);
1826 priv->zoom_multiplier = IMAGE_VIEW_ZOOM_MULTIPLIER1.05;
1827 priv->image = NULL((void*)0);
1828 priv->pixbuf = NULL((void*)0);
1829 priv->surface = NULL((void*)0);
1830 priv->transp_style = EOC_TRANSP_BACKGROUND;
1831 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", 1831, (
(const char*) (__func__)), "cdk_rgba_parse(&priv->transp_color, CHECK_BLACK)"
); } while (0)
;
1832 priv->cursor = EOC_SCROLL_VIEW_CURSOR_NORMAL;
1833 priv->menu = NULL((void*)0);
1834 priv->background_color = NULL((void*)0);
1835
1836 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
()))))))
;
1837 g_signal_connect (priv->hadj, "value_changed",g_signal_connect_data ((priv->hadj), ("value_changed"), ((
(GCallback) (adjustment_changed_cb))), (view), ((void*)0), (GConnectFlags
) 0)
1838 G_CALLBACK (adjustment_changed_cb),g_signal_connect_data ((priv->hadj), ("value_changed"), ((
(GCallback) (adjustment_changed_cb))), (view), ((void*)0), (GConnectFlags
) 0)
1839 view)g_signal_connect_data ((priv->hadj), ("value_changed"), ((
(GCallback) (adjustment_changed_cb))), (view), ((void*)0), (GConnectFlags
) 0)
;
1840
1841 priv->hbar = ctk_scrollbar_new (CTK_ORIENTATION_HORIZONTAL, priv->hadj);
1842 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
()))))))
;
1843 g_signal_connect (priv->vadj, "value_changed",g_signal_connect_data ((priv->vadj), ("value_changed"), ((
(GCallback) (adjustment_changed_cb))), (view), ((void*)0), (GConnectFlags
) 0)
1844 G_CALLBACK (adjustment_changed_cb),g_signal_connect_data ((priv->vadj), ("value_changed"), ((
(GCallback) (adjustment_changed_cb))), (view), ((void*)0), (GConnectFlags
) 0)
1845 view)g_signal_connect_data ((priv->vadj), ("value_changed"), ((
(GCallback) (adjustment_changed_cb))), (view), ((void*)0), (GConnectFlags
) 0)
;
1846
1847 priv->vbar = ctk_scrollbar_new (CTK_ORIENTATION_VERTICAL, priv->vadj);
1848 priv->display = g_object_new (CTK_TYPE_DRAWING_AREA(ctk_drawing_area_get_type ()),
1849 "can-focus", TRUE(!(0)),
1850 NULL((void*)0));
1851 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 ()))))))
);
1852
1853 ctk_widget_add_events (CTK_WIDGET (priv->display)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->display)), ((ctk_widget_get_type ()))))))
,
1854 CDK_EXPOSURE_MASK
1855 | CDK_BUTTON_PRESS_MASK
1856 | CDK_BUTTON_RELEASE_MASK
1857 | CDK_POINTER_MOTION_MASK
1858 | CDK_POINTER_MOTION_HINT_MASK
1859 | CDK_SCROLL_MASK
1860 | CDK_KEY_PRESS_MASK);
1861 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)
1862 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)
;
1863 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)
;
1864 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)
1865 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)
;
1866 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)
1867 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)
1868 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)
;
1869 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)
1870 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)
;
1871 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)
1872 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)
1873 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)
;
1874 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)
1875 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)
;
1876 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)
1877 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)
;
1878 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)
1879 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)
;
1880
1881 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)
1882 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)
;
1883
1884 ctk_drag_source_set (priv->display, CDK_BUTTON1_MASK,
1885 target_table, G_N_ELEMENTS (target_table)(sizeof (target_table) / sizeof ((target_table)[0])),
1886 CDK_ACTION_COPY | CDK_ACTION_MOVE |
1887 CDK_ACTION_LINK | CDK_ACTION_ASK);
1888 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)
1889 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)
;
1890 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)
1891 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)
;
1892
1893 ctk_grid_attach (CTK_GRID (view)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), ((ctk_grid_get_type ()))))))
, priv->display,
1894 0, 0, 1, 1);
1895 ctk_widget_set_hexpand (priv->display, TRUE(!(0)));
1896 ctk_widget_set_vexpand (priv->display, TRUE(!(0)));
1897 ctk_grid_attach (CTK_GRID (view)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), ((ctk_grid_get_type ()))))))
, priv->hbar,
1898 0, 1, 1, 1);
1899 ctk_widget_set_hexpand (priv->hbar, TRUE(!(0)));
1900 ctk_grid_attach (CTK_GRID (view)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), ((ctk_grid_get_type ()))))))
, priv->vbar,
1901 1, 0, 1, 1);
1902 ctk_widget_set_vexpand (priv->vbar, TRUE(!(0)));
1903
1904 g_settings_bind (settings, EOC_CONF_VIEW_USE_BG_COLOR"use-background-color", view,
1905 "use-background-color", G_SETTINGS_BIND_DEFAULT);
1906 g_settings_bind_with_mapping (settings, EOC_CONF_VIEW_BACKGROUND_COLOR"background-color",
1907 view, "background-color",
1908 G_SETTINGS_BIND_DEFAULT,
1909 sv_string_to_rgba_mapping,
1910 sv_rgba_to_string_mapping, NULL((void*)0), NULL((void*)0));
1911 g_settings_bind (settings, EOC_CONF_VIEW_EXTRAPOLATE"extrapolate", view,
1912 "antialiasing-in", G_SETTINGS_BIND_GET);
1913 g_settings_bind (settings, EOC_CONF_VIEW_INTERPOLATE"interpolate", view,
1914 "antialiasing-out", G_SETTINGS_BIND_GET);
1915 g_settings_bind_with_mapping (settings, EOC_CONF_VIEW_TRANS_COLOR"trans-color",
1916 view, "transparency-color",
1917 G_SETTINGS_BIND_GET,
1918 sv_string_to_rgba_mapping,
1919 sv_rgba_to_string_mapping, NULL((void*)0), NULL((void*)0));
1920 g_settings_bind (settings, EOC_CONF_VIEW_TRANSPARENCY"transparency", view,
1921 "transparency-style", G_SETTINGS_BIND_GET);
1922
1923 g_object_unref (settings);
1924
1925 priv->override_bg_color = NULL((void*)0);
1926 priv->background_surface = NULL((void*)0);
1927}
1928
1929static void
1930eoc_scroll_view_dispose (GObject *object)
1931{
1932 EocScrollView *view;
1933 EocScrollViewPrivate *priv;
1934
1935 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)
;
1936
1937 view = EOC_SCROLL_VIEW (object)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((eoc_scroll_view_get_type ()))))))
;
1938 priv = view->priv;
1939
1940 _clear_hq_redraw_timeout (view);
1941
1942 if (priv->idle_id != 0) {
1943 g_source_remove (priv->idle_id);
1944 priv->idle_id = 0;
1945 }
1946
1947 if (priv->background_color != NULL((void*)0)) {
1948 cdk_rgba_free (priv->background_color);
1949 priv->background_color = NULL((void*)0);
1950 }
1951
1952 if (priv->override_bg_color != NULL((void*)0)) {
1953 cdk_rgba_free (priv->override_bg_color);
1954 priv->override_bg_color = NULL((void*)0);
1955 }
1956
1957 if (priv->background_surface != NULL((void*)0)) {
1958 cairo_surface_destroy (priv->background_surface);
1959 priv->background_surface = NULL((void*)0);
1960 }
1961
1962 free_image_resources (view);
1963
1964 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);
1965}
1966
1967static void
1968eoc_scroll_view_get_property (GObject *object, guint property_id,
1969 GValue *value, GParamSpec *pspec)
1970{
1971 EocScrollView *view;
1972 EocScrollViewPrivate *priv;
1973
1974 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)
;
1975
1976 view = EOC_SCROLL_VIEW (object)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((eoc_scroll_view_get_type ()))))))
;
1977 priv = view->priv;
1978
1979 switch (property_id) {
1980 case PROP_ANTIALIAS_IN:
1981 {
1982 gboolean filter = (priv->interp_type_in != CAIRO_FILTER_NEAREST);
1983 g_value_set_boolean (value, filter);
1984 break;
1985 }
1986 case PROP_ANTIALIAS_OUT:
1987 {
1988 gboolean filter = (priv->interp_type_out != CAIRO_FILTER_NEAREST);
1989 g_value_set_boolean (value, filter);
1990 break;
1991 }
1992 case PROP_USE_BG_COLOR:
1993 g_value_set_boolean (value, priv->use_bg_color);
1994 break;
1995 case PROP_BACKGROUND_COLOR:
1996 //FIXME: This doesn't really handle the NULL color.
1997 g_value_set_boxed (value, priv->background_color);
1998 break;
1999 case PROP_SCROLLWHEEL_ZOOM:
2000 g_value_set_boolean (value, priv->scroll_wheel_zoom);
2001 break;
2002 case PROP_TRANSPARENCY_STYLE:
2003 g_value_set_enum (value, priv->transp_style);
2004 break;
2005 case PROP_ZOOM_MULTIPLIER:
2006 g_value_set_double (value, priv->zoom_multiplier);
2007 break;
2008 case PROP_IMAGE:
2009 g_value_set_object (value, priv->image);
2010 break;
2011 default:
2012 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", 2012, ("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)
;
2013 }
2014}
2015
2016static void
2017eoc_scroll_view_set_property (GObject *object, guint property_id,
2018 const GValue *value, GParamSpec *pspec)
2019{
2020 EocScrollView *view;
2021
2022 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)
;
2023
2024 view = EOC_SCROLL_VIEW (object)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((eoc_scroll_view_get_type ()))))))
;
2025
2026 switch (property_id) {
2027 case PROP_ANTIALIAS_IN:
2028 eoc_scroll_view_set_antialiasing_in (view, g_value_get_boolean (value));
2029 break;
2030 case PROP_ANTIALIAS_OUT:
2031 eoc_scroll_view_set_antialiasing_out (view, g_value_get_boolean (value));
2032 break;
2033 case PROP_USE_BG_COLOR:
2034 eoc_scroll_view_set_use_bg_color (view, g_value_get_boolean (value));
2035 break;
2036 case PROP_BACKGROUND_COLOR:
2037 {
2038 const CdkRGBA *color = g_value_get_boxed (value);
2039 eoc_scroll_view_set_background_color (view, color);
2040 break;
2041 }
2042 case PROP_SCROLLWHEEL_ZOOM:
2043 eoc_scroll_view_set_scroll_wheel_zoom (view, g_value_get_boolean (value));
2044 break;
2045 case PROP_TRANSP_COLOR:
2046 eoc_scroll_view_set_transparency_color (view, g_value_get_boxed (value));
2047 break;
2048 case PROP_TRANSPARENCY_STYLE:
2049 eoc_scroll_view_set_transparency (view, g_value_get_enum (value));
2050 break;
2051 case PROP_ZOOM_MULTIPLIER:
2052 eoc_scroll_view_set_zoom_multiplier (view, g_value_get_double (value));
2053 break;
2054 case PROP_IMAGE:
2055 eoc_scroll_view_set_image (view, g_value_get_object (value));
2056 break;
2057 default:
2058 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", 2058, ("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)
;
2059 }
2060}
2061
2062
2063static void
2064eoc_scroll_view_class_init (EocScrollViewClass *klass)
2065{
2066 GObjectClass *gobject_class;
2067 CtkWidgetClass *widget_class;
2068
2069 gobject_class = (GObjectClass*) klass;
2070 widget_class = (CtkWidgetClass*) klass;
2071
2072 gobject_class->dispose = eoc_scroll_view_dispose;
2073 gobject_class->set_property = eoc_scroll_view_set_property;
2074 gobject_class->get_property = eoc_scroll_view_get_property;
2075
2076 g_object_class_install_property (
2077 gobject_class, PROP_ANTIALIAS_IN,
2078 g_param_spec_boolean ("antialiasing-in", NULL((void*)0), NULL((void*)0), TRUE(!(0)),
2079 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2080
2081 g_object_class_install_property (
2082 gobject_class, PROP_ANTIALIAS_OUT,
2083 g_param_spec_boolean ("antialiasing-out", NULL((void*)0), NULL((void*)0), TRUE(!(0)),
2084 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2085
2086 /**
2087 * EocScrollView:background-color:
2088 *
2089 * This is the default background color used for painting the background
2090 * of the image view. If set to %NULL the color is determined by the
2091 * active CTK theme.
2092 */
2093 g_object_class_install_property (
2094 gobject_class, PROP_BACKGROUND_COLOR,
2095 g_param_spec_boxed ("background-color", NULL((void*)0), NULL((void*)0),
2096 CDK_TYPE_RGBA(cdk_rgba_get_type ()),
2097 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2098
2099 g_object_class_install_property (
2100 gobject_class, PROP_USE_BG_COLOR,
2101 g_param_spec_boolean ("use-background-color", NULL((void*)0), NULL((void*)0), FALSE(0),
2102 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2103
2104 /**
2105 * EocScrollView:zoom-multiplier:
2106 *
2107 * The current zoom factor is multiplied with this value + 1.0 when
2108 * scrolling with the scrollwheel to determine the next zoom factor.
2109 */
2110 g_object_class_install_property (
2111 gobject_class, PROP_ZOOM_MULTIPLIER,
2112 g_param_spec_double ("zoom-multiplier", NULL((void*)0), NULL((void*)0),
2113 -G_MAXDOUBLE1.7976931348623157e+308, G_MAXDOUBLE1.7976931348623157e+308 -1.0, 0.05,
2114 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2115
2116 /**
2117 * EocScrollView:scrollwheel-zoom:
2118 *
2119 * If %TRUE the scrollwheel will zoom the view, otherwise it will be
2120 * used for scrolling a zoomed image.
2121 */
2122 g_object_class_install_property (
2123 gobject_class, PROP_SCROLLWHEEL_ZOOM,
2124 g_param_spec_boolean ("scrollwheel-zoom", NULL((void*)0), NULL((void*)0), TRUE(!(0)),
2125 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2126
2127 /**
2128 * EocScrollView:image:
2129 *
2130 * This is the currently display #EocImage.
2131 */
2132 g_object_class_install_property (
2133 gobject_class, PROP_IMAGE,
2134 g_param_spec_object ("image", NULL((void*)0), NULL((void*)0), EOC_TYPE_IMAGE(eoc_image_get_type ()),
2135 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2136
2137 /**
2138 * EocScrollView:transparency-color:
2139 *
2140 * This is the color used to fill the transparent parts of an image
2141 * if :transparency-style is set to use a custom color.
2142 */
2143 g_object_class_install_property (
2144 gobject_class, PROP_TRANSP_COLOR,
2145 g_param_spec_boxed ("transparency-color", NULL((void*)0), NULL((void*)0),
2146 CDK_TYPE_RGBA(cdk_rgba_get_type ()),
2147 G_PARAM_WRITABLE | G_PARAM_STATIC_NAME));
2148
2149 /**
2150 * EocScrollView:transparency-style:
2151 *
2152 * Determines how to fill the shown image's transparent areas.
2153 */
2154 g_object_class_install_property (
2155 gobject_class, PROP_TRANSPARENCY_STYLE,
2156 g_param_spec_enum ("transparency-style", NULL((void*)0), NULL((void*)0),
2157 EOC_TYPE_TRANSPARENCY_STYLE(eoc_transparency_style_get_type()),
2158 EOC_TRANSP_CHECKED,
2159 G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
2160
2161 view_signals [SIGNAL_ZOOM_CHANGED] =
2162 g_signal_new ("zoom_changed",
2163 EOC_TYPE_SCROLL_VIEW(eoc_scroll_view_get_type ()),
2164 G_SIGNAL_RUN_LAST,
2165 G_STRUCT_OFFSET (EocScrollViewClass, zoom_changed)((glong) __builtin_offsetof(EocScrollViewClass, zoom_changed)
)
,
2166 NULL((void*)0), NULL((void*)0),
2167 eoc_marshal_VOID__DOUBLEg_cclosure_marshal_VOID__DOUBLE,
2168 G_TYPE_NONE((GType) ((1) << (2))), 1,
2169 G_TYPE_DOUBLE((GType) ((15) << (2))));
2170
2171 widget_class->size_allocate = eoc_scroll_view_size_allocate;
2172}
2173
2174static void
2175view_on_drag_begin_cb (CtkWidget *widget,
2176 CdkDragContext *context,
2177 gpointer user_data)
2178{
2179 EocScrollView *view;
2180 EocImage *image;
2181 GdkPixbuf *thumbnail;
2182 gint width, height;
2183
2184 view = EOC_SCROLL_VIEW (user_data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((eoc_scroll_view_get_type ()))))))
;
2185 image = view->priv->image;
2186
2187 thumbnail = eoc_image_get_thumbnail (image);
2188
2189 if (thumbnail) {
2190 width = gdk_pixbuf_get_width (thumbnail) / view->priv->scale;
2191 height = gdk_pixbuf_get_height (thumbnail) / view->priv->scale;
2192 ctk_drag_set_icon_pixbuf (context, thumbnail, width/2, height/2);
2193 g_object_unref (thumbnail);
2194 }
2195}
2196
2197static void
2198view_on_drag_data_get_cb (CtkWidget *widget,
2199 CdkDragContext *drag_context,
2200 CtkSelectionData *data,
2201 guint info,
2202 guint time,
2203 gpointer user_data)
2204{
2205 EocScrollView *view;
2206 EocImage *image;
2207 gchar *uris[2];
2208 GFile *file;
2209
2210 view = EOC_SCROLL_VIEW (user_data)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((eoc_scroll_view_get_type ()))))))
;
2211
2212 image = view->priv->image;
2213
2214 file = eoc_image_get_file (image);
2215 uris[0] = g_file_get_uri (file);
2216 uris[1] = NULL((void*)0);
2217
2218 ctk_selection_data_set_uris (data, uris);
2219
2220 g_free (uris[0]);
2221 g_object_unref (file);
2222}
2223
2224CtkWidget*
2225eoc_scroll_view_new (void)
2226{
2227 CtkWidget *widget;
2228
2229 widget = g_object_new (EOC_TYPE_SCROLL_VIEW(eoc_scroll_view_get_type ()),
2230 "can-focus", TRUE(!(0)),
2231 "row-homogeneous", FALSE(0),
2232 "column-homogeneous", FALSE(0),
2233 NULL((void*)0));
2234
2235
2236 return widget;
2237}
2238
2239static gboolean
2240view_on_button_press_event_cb (CtkWidget *widget, CdkEventButton *event,
2241 gpointer user_data)
2242{
2243 EocScrollView *view = EOC_SCROLL_VIEW (widget)((((EocScrollView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((eoc_scroll_view_get_type ()))))))
;
2244
2245 /* Ignore double-clicks and triple-clicks */
2246 if (event->button == 3 && event->type == CDK_BUTTON_PRESS)
2247 {
2248 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 ()))))))
,
2249 (const CdkEvent*) event);
2250
2251 return TRUE(!(0));
2252 }
2253
2254 return FALSE(0);
2255}
2256
2257void
2258eoc_scroll_view_set_popup (EocScrollView *view,
2259 CtkMenu *menu)
2260{
2261 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)
;
2262 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)
;
2263
2264 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 ()))))))))
;
2265
2266 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 ()))))))
,
2267 CTK_WIDGET (view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), ((ctk_widget_get_type ()))))))
,
2268 NULL((void*)0));
2269
2270 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)
2271 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)
;
2272}
2273
2274static gboolean
2275_eoc_cdk_rgba_equal0 (const CdkRGBA *a, const CdkRGBA *b)
2276{
2277 if (a == NULL((void*)0) || b == NULL((void*)0))
2278 return (a == b);
2279
2280 return cdk_rgba_equal (a, b);
2281}
2282
2283static gboolean
2284_eoc_replace_cdk_rgba (CdkRGBA **dest, const CdkRGBA *src)
2285{
2286 CdkRGBA *old = *dest;
2287
2288 if (_eoc_cdk_rgba_equal0 (old, src))
2289 return FALSE(0);
2290
2291 if (old != NULL((void*)0))
2292 cdk_rgba_free (old);
2293
2294 *dest = (src) ? cdk_rgba_copy (src) : NULL((void*)0);
2295
2296 return TRUE(!(0));
2297}
2298
2299static void
2300_eoc_scroll_view_update_bg_color (EocScrollView *view)
2301{
2302 EocScrollViewPrivate *priv = view->priv;
2303
2304 if (priv->transp_style == EOC_TRANSP_BACKGROUND
2305 && priv->background_surface != NULL((void*)0)) {
2306 /* Delete the SVG background to have it recreated with
2307 * the correct color during the next SVG redraw */
2308 cairo_surface_destroy (priv->background_surface);
2309 priv->background_surface = NULL((void*)0);
2310 }
2311
2312 ctk_widget_queue_draw (priv->display);
2313}
2314
2315void
2316eoc_scroll_view_set_background_color (EocScrollView *view,
2317 const CdkRGBA *color)
2318{
2319 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)
;
2320
2321 if (_eoc_replace_cdk_rgba (&view->priv->background_color, color))
2322 _eoc_scroll_view_update_bg_color (view);
2323}
2324
2325void
2326eoc_scroll_view_override_bg_color (EocScrollView *view,
2327 const CdkRGBA *color)
2328{
2329 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)
;
2330
2331 if (_eoc_replace_cdk_rgba (&view->priv->override_bg_color, color))
2332 _eoc_scroll_view_update_bg_color (view);
2333}
2334
2335void
2336eoc_scroll_view_set_use_bg_color (EocScrollView *view, gboolean use)
2337{
2338 EocScrollViewPrivate *priv;
2339
2340 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)
;
2341
2342 priv = view->priv;
2343
2344 if (use != priv->use_bg_color) {
2345 priv->use_bg_color = use;
2346
2347 _eoc_scroll_view_update_bg_color (view);
2348
2349 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "use-background-color");
2350 }
2351}
2352
2353void
2354eoc_scroll_view_set_scroll_wheel_zoom (EocScrollView *view,
2355 gboolean scroll_wheel_zoom)
2356{
2357 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)
;
2358
2359 if (view->priv->scroll_wheel_zoom != scroll_wheel_zoom) {
2360 view->priv->scroll_wheel_zoom = scroll_wheel_zoom;
2361 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "scrollwheel-zoom");
2362 }
2363}
2364
2365void
2366eoc_scroll_view_set_zoom_multiplier (EocScrollView *view,
2367 gdouble zoom_multiplier)
2368{
2369 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)
;
2370
2371 view->priv->zoom_multiplier = 1.0 + zoom_multiplier;
2372
2373 g_object_notify (G_OBJECT (view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((view)), (((GType) ((20) << (2))))))))
, "zoom-multiplier");
2374}