Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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