📄 pixbuf-renderer.c
字号:
pr_queue(pr, 0, 0, pr->width, pr->height, TRUE, TILE_RENDER_ALL, new_data, FALSE);}/* *------------------------------------------------------------------- * signal emission *------------------------------------------------------------------- */static void pr_update_signal(PixbufRenderer *pr){#if 0 printf("FIXME: send updated signal\n");#endif}static void pr_zoom_signal(PixbufRenderer *pr){ g_signal_emit(pr, signals[SIGNAL_ZOOM], 0, pr->zoom);}static void pr_clicked_signal(PixbufRenderer *pr, GdkEventButton *bevent){ g_signal_emit(pr, signals[SIGNAL_CLICKED], 0, bevent);}static void pr_scroll_notify_signal(PixbufRenderer *pr){ g_signal_emit(pr, signals[SIGNAL_SCROLL_NOTIFY], 0);}static void pr_render_complete_signal(PixbufRenderer *pr){ if (!pr->complete) { g_signal_emit(pr, signals[SIGNAL_RENDER_COMPLETE], 0); g_object_set(G_OBJECT(pr), "complete", TRUE, NULL); }}/* *------------------------------------------------------------------- * sync and clamp *------------------------------------------------------------------- */static gint pr_scroll_clamp(PixbufRenderer *pr){ gint old_xs; gint old_ys; if (pr->zoom == 0.0) { pr->x_scroll = 0; pr->y_scroll = 0; return FALSE; } old_xs = pr->x_scroll; old_ys = pr->y_scroll; if (pr->x_offset > 0) { pr->x_scroll = 0; } else { pr->x_scroll = CLAMP(pr->x_scroll, 0, pr->width - pr->vis_width); } if (pr->y_offset > 0) { pr->y_scroll = 0; } else { pr->y_scroll = CLAMP(pr->y_scroll, 0, pr->height - pr->vis_height); } return (old_xs != pr->x_scroll || old_ys != pr->y_scroll);}static gint pr_size_clamp(PixbufRenderer *pr){ gint old_vw, old_vh; old_vw = pr->vis_width; old_vh = pr->vis_height; if (pr->width < pr->window_width) { pr->vis_width = pr->width; pr->x_offset = (pr->window_width - pr->width) / 2; } else { pr->vis_width = pr->window_width; pr->x_offset = 0; } if (pr->height < pr->window_height) { pr->vis_height = pr->height; pr->y_offset = (pr->window_height - pr->height) / 2; } else { pr->vis_height = pr->window_height; pr->y_offset = 0; } return (old_vw != pr->vis_width || old_vh != pr->vis_height);}static gint pr_zoom_clamp(PixbufRenderer *pr, gdouble zoom, gint force, gint new, gint invalidate, gint *redrawn){ gint w, h; gdouble scale; gint invalid; zoom = CLAMP(zoom, pr->zoom_min, pr->zoom_max); if (pr->zoom == zoom && !force) return FALSE; w = pr->image_width; h = pr->image_height; if (zoom == 0.0 && !pr->pixbuf) { scale = 1.0; } else if (zoom == 0.0) { gint max_w; gint max_h; gint sizeable; sizeable = (new && pr_parent_window_sizable(pr)); if (sizeable) { max_w = gdk_screen_width(); max_h = gdk_screen_height(); if (pr->window_limit) { max_w = max_w * pr->window_limit_size / 100; max_h = max_h * pr->window_limit_size / 100; } } else { max_w = pr->window_width; max_h = pr->window_height; } if ((pr->zoom_expand && !sizeable) || w > max_w || h > max_h) { if ((gdouble)max_w / w > (gdouble)max_h / h) { scale = (gdouble)max_h / h; h = max_h; w = w * scale + 0.5; if (w > max_w) w = max_w; } else { scale = (gdouble)max_w / w; w = max_w; h = h * scale + 0.5; if (h > max_h) h = max_h; } if (w < 1) w = 1; if (h < 1) h = 1; } else { scale = 1.0; } } else if (zoom > 0.0) /* zoom orig, in */ { scale = zoom; w = w * scale; h = h * scale; } else /* zoom out */ { scale = 1.0 / (0.0 - zoom); w = w * scale; h = h * scale; } invalid = (pr->width != w || pr->height != h); pr->zoom = zoom; pr->width = w; pr->height = h; pr->scale = scale; if (invalidate || invalid) { pr_tile_invalidate_all(pr); pr_redraw(pr, TRUE); } if (redrawn) *redrawn = (invalidate || invalid); return TRUE;}static void pr_zoom_sync(PixbufRenderer *pr, gdouble zoom, gint force, gint blank, gint new, gint center_point, gint px, gint py){ gdouble old_scale; gint old_cx, old_cy; gint clamped; gint sized; gint redrawn = FALSE; old_scale = pr->scale; if (center_point) { px = CLAMP(px, 0, pr->width); py = CLAMP(py, 0, pr->height); old_cx = pr->x_scroll + (px - pr->x_offset); old_cy = pr->y_scroll + (py - pr->y_offset); } else { px = py = 0; old_cx = pr->x_scroll + pr->vis_width / 2; old_cy = pr->y_scroll + pr->vis_height / 2; } if (!pr_zoom_clamp(pr, zoom, force, new, force, &redrawn)) return; clamped = pr_size_clamp(pr); sized = pr_parent_window_resize(pr, pr->width, pr->height); if (force) { switch (pr->scroll_reset) { case PR_SCROLL_RESET_NOCHANGE: /* maintain old scroll position, do nothing */ break; case PR_SCROLL_RESET_CENTER: /* center new image */ pr->x_scroll = ((double)pr->image_width / 2.0 * pr->scale) - pr->vis_width / 2; pr->y_scroll = ((double)pr->image_height / 2.0 * pr->scale) - pr->vis_height / 2; break; case PR_SCROLL_RESET_TOPLEFT: default: /* reset to upper left */ pr->x_scroll = 0; pr->y_scroll = 0; break; } } else { /* user zoom does not force, so keep visible center point */ if (center_point) { pr->x_scroll = old_cx / old_scale * pr->scale - (px - pr->x_offset); pr->y_scroll = old_cy / old_scale * pr->scale - (py - pr->y_offset); } else { pr->x_scroll = old_cx / old_scale * pr->scale - (pr->vis_width / 2); pr->y_scroll = old_cy / old_scale * pr->scale - (pr->vis_height / 2); } } pr_scroll_clamp(pr);#if 0 pr_tile_sync(pr, blank);#endif /* If the window was not sized, redraw the image - we know there will be no size/expose signal. * But even if a size is claimed, there is no guarantee that the window manager will allow it, * so redraw the window anyway :/ */ if (sized || clamped) pr_border_clear(pr); pr_redraw(pr, redrawn); pr_scroll_notify_signal(pr); pr_zoom_signal(pr); pr_update_signal(pr);}static void pr_size_sync(PixbufRenderer *pr, gint new_width, gint new_height){ gint zoom_changed = FALSE; if (pr->window_width == new_width && pr->window_height == new_height) return; pr->window_width = new_width; pr->window_height = new_height; if (pr->zoom == 0.0) { gdouble old_scale = pr->scale; pr_zoom_clamp(pr, 0.0, TRUE, FALSE, FALSE, NULL); zoom_changed = (old_scale != pr->scale); } pr_size_clamp(pr); pr_scroll_clamp(pr); /* ensure scroller remains visible */ if (pr->scroller_overlay != -1) { gint update = FALSE; if (pr->scroller_x > new_width) { pr->scroller_x = new_width; pr->scroller_xpos = new_width; update = TRUE; } if (pr->scroller_y > new_height) { pr->scroller_y = new_height; pr->scroller_ypos = new_height; update = TRUE; } if (update) { GdkPixbuf *pixbuf; if (pixbuf_renderer_overlay_get(pr, pr->scroller_overlay, &pixbuf, NULL, NULL)) { gint w, h; w = gdk_pixbuf_get_width(pixbuf); h = gdk_pixbuf_get_height(pixbuf); pixbuf_renderer_overlay_set(pr, pr->scroller_overlay, pixbuf, pr->scroller_x - w / 2, pr->scroller_y - h / 2); } } } pr_border_clear(pr);#if 0 pr_tile_sync(pr, pr->width, pr->height, FALSE);#endif pr_scroll_notify_signal(pr); if (zoom_changed) pr_zoom_signal(pr); pr_update_signal(pr);}static void pr_size_cb(GtkWidget *widget, GtkAllocation *allocation, gpointer data){ PixbufRenderer *pr = data; pr_size_sync(pr, allocation->width, allocation->height);}static void pixbuf_renderer_paint(PixbufRenderer *pr, GdkRectangle *area){ gint x, y; pr_border_draw(pr, area->x, area->y, area->width, area->height); x = MAX(0, (gint)area->x - pr->x_offset + pr->x_scroll); y = MAX(0, (gint)area->y - pr->y_offset + pr->y_scroll); pr_queue(pr, x, y, MIN((gint)area->width, pr->width - x), MIN((gint)area->height, pr->height - y), FALSE, TILE_RENDER_ALL, FALSE, FALSE);}/* *------------------------------------------------------------------- * scrolling *------------------------------------------------------------------- */void pixbuf_renderer_scroll(PixbufRenderer *pr, gint x, gint y){ gint old_x, old_y; gint x_off, y_off; gint w, h; g_return_if_fail(IS_PIXBUF_RENDERER(pr)); if (!pr->pixbuf && !pr->source_tiles_enabled) return; old_x = pr->x_scroll; old_y = pr->y_scroll; pr->x_scroll += x; pr->y_scroll += y; pr_scroll_clamp(pr); if (pr->x_scroll == old_x && pr->y_scroll == old_y) return; pr_scroll_notify_signal(pr); if (pr->overlay_list) { gint new_x, new_y; new_x = pr->x_scroll; new_y = pr->y_scroll; pr->x_scroll = old_x; pr->y_scroll = old_y; pr_overlay_queue_all(pr); pr->x_scroll = new_x; pr->y_scroll = new_y; } x_off = pr->x_scroll - old_x; y_off = pr->y_scroll - old_y; w = pr->vis_width - abs(x_off); h = pr->vis_height - abs(y_off); if (w < 1 || h < 1) { /* scrolled completely to new material */ pr_queue(pr, 0, 0, pr->width, pr->height, TRUE, TILE_RENDER_ALL, FALSE, FALSE); return; } else { gint x1, y1; gint x2, y2; GtkWidget *box; GdkGC *gc; if (x_off < 0) { x1 = abs(x_off); x2 = 0; } else { x1 = 0; x2 = abs(x_off); } if (y_off < 0) { y1 = abs(y_off); y2 = 0; } else { y1 = 0; y2 = abs(y_off); } box = GTK_WIDGET(pr); gc = gdk_gc_new(box->window); gdk_gc_set_exposures(gc, TRUE); gdk_draw_drawable(box->window, gc, box->window, x2 + pr->x_offset, y2 + pr->y_offset, x1 + pr->x_offset, y1 + pr->y_offset, w, h); g_object_unref(gc); if (pr->overlay_list) { pr_overlay_queue_all(pr); } w = pr->vis_width - w; h = pr->vis_height - h; if (w > 0) { pr_queue(pr, x_off > 0 ? pr->x_scroll + (pr->vis_width - w) : pr->x_scroll, pr->y_scroll, w, pr->vis_height, TRUE, TILE_RENDER_ALL, FALSE, FALSE); } if (h > 0) { /* FIXME, to optimize this, remove overlap */ pr_queue(pr, pr->x_scroll, y_off > 0 ? pr->y_scroll + (pr->vis_height - h) : pr->y_scroll, pr->vis_width, h, TRUE, TILE_RENDER_ALL, FALSE, FALSE); } }}void pixbuf_renderer_scroll_to_point(PixbufRenderer *pr, gint x, gint y, gdouble x_align, gdouble y_align){ gint px, py; gint ax, ay; x_align = CLAMP(x_align, 0.0, 1.0); y_align = CLAMP(y_align, 0.0, 1.0); ax = (gdouble)pr->vis_width * x_align; ay = (gdouble)pr->vis_height * y_align; px = (gdouble)x * pr->scale - (pr->x_scroll + ax); py = (gdouble)y * pr->scale - (pr->y_scroll + ay); pixbuf_renderer_scroll(pr, px, py);}/* *------------------------------------------------------------------- * mouse *------------------------------------------------------------------- */static gint pr_mouse_motion_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data){ PixbufRenderer *pr; gint accel; pr = PIXBUF_RENDERER(widget); if (pr->scroller_id != -1) { pr->scroller_xpos = bevent->x; pr->scroller_ypos = bevent->y; } if (!pr->in_drag || !gdk_pointer_is_grabbed()) return FALSE; if (pr->drag_moved < PR_DRAG_SCROLL_THRESHHOLD) { pr->drag_moved++; } else { widget_set_cursor(widget, GDK_FLEUR); } if (bevent->state & GDK_SHIFT_MASK) { accel = PR_PAN_SHIFT_MULTIPLIER; } else { accel = 1; } /* do the scroll */ pixbuf_renderer_scroll(pr, (pr->drag_last_x - bevent->x) * accel, (pr->drag_last_y - bevent->y) * accel); pr->drag_last_x = bevent->x; pr->drag_last_y = bevent->y; return FALSE;}static gint pr_mouse_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data){ PixbufRenderer *pr; GtkWidget *parent; pr = PIXBUF_RENDERER(widget); if (pr->scroller_id != -1) return TRUE; switch (bevent->button) { case 1: pr->in_drag = TRUE; pr->d
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -