📄 pixbuf-renderer.c
字号:
g_value_set_boolean(value, pr->loading); break; case PROP_COMPLETE: g_value_set_boolean(value, pr->complete); break; case PROP_CACHE_SIZE_DISPLAY: g_value_set_uint(value, pr->tile_cache_max); break; case PROP_CACHE_SIZE_TILES: g_value_set_uint(value, pr->source_tiles_cache_size); break; case PROP_WINDOW_FIT: g_value_set_boolean(value, pr->window_fit); break; case PROP_WINDOW_LIMIT: g_value_set_boolean(value, pr->window_limit); break; case PROP_WINDOW_LIMIT_VALUE: g_value_set_uint(value, pr->window_limit_size); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; }}static gint pixbuf_renderer_expose(GtkWidget *widget, GdkEventExpose *event){ if (GTK_WIDGET_DRAWABLE(widget)) { if (!GTK_WIDGET_NO_WINDOW(widget)) { pixbuf_renderer_paint(PIXBUF_RENDERER(widget), &event->area); } } return FALSE;}/* *------------------------------------------------------------------- * misc utilities *------------------------------------------------------------------- */static void widget_set_cursor(GtkWidget *widget, gint icon){ GdkCursor *cursor; if (!widget->window) return; if (icon == -1) { cursor = NULL; } else { cursor = gdk_cursor_new (icon); } gdk_window_set_cursor(widget->window, cursor); if (cursor) gdk_cursor_unref(cursor);}static gint pixmap_calc_size(GdkPixmap *pixmap){ gint w, h, d; d = gdk_drawable_get_depth(pixmap); gdk_drawable_get_size(pixmap, &w, &h); return w * h * (d / 8);}static gint pr_clip_region(gint x, gint y, gint w, gint h, gint clip_x, gint clip_y, gint clip_w, gint clip_h, gint *rx, gint *ry, gint *rw, gint *rh){ if (clip_x + clip_w <= x || clip_x >= x + w || clip_y + clip_h <= y || clip_y >= y + h) { return FALSE; } *rx = MAX(x, clip_x); *rw = MIN((x + w), (clip_x + clip_w)) - *rx; *ry = MAX(y, clip_y); *rh = MIN((y + h), (clip_y + clip_h)) - *ry; return TRUE;}static gint pr_parent_window_sizable(PixbufRenderer *pr){ GdkWindowState state; if (!pr->parent_window) return FALSE; if (!pr->window_fit) return FALSE; if (!GTK_WIDGET(pr)->window) return FALSE; if (!pr->parent_window->window) return FALSE; state = gdk_window_get_state(pr->parent_window->window); if (state & GDK_WINDOW_STATE_MAXIMIZED) return FALSE; return TRUE;}static gint pr_parent_window_resize(PixbufRenderer *pr, gint w, gint h){ GtkWidget *widget; GtkWidget *parent; gint ww, wh; if (!pr_parent_window_sizable(pr)) return FALSE; if (pr->window_limit) { gint sw = gdk_screen_width() * pr->window_limit_size / 100; gint sh = gdk_screen_height() * pr->window_limit_size / 100; if (w > sw) w = sw; if (h > sh) h = sh; } widget = GTK_WIDGET(pr); parent = GTK_WIDGET(pr->parent_window); w += (parent->allocation.width - widget->allocation.width); h += (parent->allocation.height - widget->allocation.height); gdk_drawable_get_size(parent->window, &ww, &wh); if (w == ww && h == wh) return FALSE; gdk_window_resize(parent->window, w, h); return TRUE;}void pixbuf_renderer_set_parent(PixbufRenderer *pr, GtkWindow *window){ g_return_if_fail(IS_PIXBUF_RENDERER(pr)); g_return_if_fail(window == NULL || GTK_IS_WINDOW(window)); pr->parent_window = GTK_WIDGET(window);}GtkWindow *pixbuf_renderer_get_parent(PixbufRenderer *pr){ g_return_val_if_fail(IS_PIXBUF_RENDERER(pr), NULL); return GTK_WINDOW(pr->parent_window);}/* *------------------------------------------------------------------- * overlays *------------------------------------------------------------------- */static void pr_overlay_draw(PixbufRenderer *pr, gint x, gint y, gint w, gint h){ GtkWidget *box; GList *work; box = GTK_WIDGET(pr); work = pr->overlay_list; while (work) { OverlayData *od; gint px, py, pw, ph; gint rx, ry, rw, rh; od = work->data; work = work->next; if (!od->visible) continue; pw = gdk_pixbuf_get_width(od->pixbuf); ph = gdk_pixbuf_get_height(od->pixbuf); px = od->x; py = od->y; if (od->relative) { if (px < 0) px = pr->window_width - pw + px; if (py < 0) py = pr->window_height - ph + py; } if (pr_clip_region(x, y, w, h, px, py, pw, ph, &rx, &ry, &rw, &rh)) { gdk_draw_pixbuf(box->window, box->style->fg_gc[GTK_WIDGET_STATE(box)], od->pixbuf, rx - px, ry - py, rx, ry, rw, rh, pr->dither_quality, rx, ry); } }}static void pr_overlay_queue_draw(PixbufRenderer *pr, OverlayData *od, gint hidden){ gint x, y, w, h; gint old_vis; w = gdk_pixbuf_get_width(od->pixbuf); h = gdk_pixbuf_get_height(od->pixbuf); x = od->x; y = od->y; if (od->relative) { if (x < 0) x = pr->window_width - w + x; if (y < 0) y = pr->window_height - h + y; } pr_queue(pr, pr->x_scroll - pr->x_offset + x, pr->y_scroll - pr->y_offset + y, w, h, FALSE, TILE_RENDER_ALL, FALSE, FALSE); old_vis = od->visible; if (hidden) od->visible = FALSE; pr_border_draw(pr, x, y, w, h); od->visible = old_vis;}static void pr_overlay_queue_all(PixbufRenderer *pr){ GList *work; work = pr->overlay_list; while (work) { OverlayData *od = work->data; work = work->next; pr_overlay_queue_draw(pr, od, FALSE); }}static OverlayData *pr_overlay_find(PixbufRenderer *pr, gint id){ GList *work; work = pr->overlay_list; while (work) { OverlayData *od = work->data; work = work->next; if (od->id == id) return od; } return NULL;}gint pixbuf_renderer_overlay_add(PixbufRenderer *pr, GdkPixbuf *pixbuf, gint x, gint y, gint relative, gint always){ OverlayData *od; gint id; g_return_val_if_fail(IS_PIXBUF_RENDERER(pr), -1); g_return_val_if_fail(pixbuf != NULL, -1); id = 1; while (pr_overlay_find(pr, id)) id++; od = g_new0(OverlayData, 1); od->id = id; od->pixbuf = pixbuf; g_object_ref(G_OBJECT(od->pixbuf)); od->x = x; od->y = y; od->relative = relative; od->visible = TRUE; od->always = always; pr->overlay_list = g_list_append(pr->overlay_list, od); pr_overlay_queue_draw(pr, od, FALSE); return od->id;}static void pr_overlay_free(PixbufRenderer *pr, OverlayData *od){ pr->overlay_list = g_list_remove(pr->overlay_list, od); if (od->pixbuf) g_object_unref(G_OBJECT(od->pixbuf)); g_free(od);}static void pr_overlay_list_clear(PixbufRenderer *pr){ while (pr->overlay_list) { OverlayData *od; od = pr->overlay_list->data; pr_overlay_free(pr, od); }}void pixbuf_renderer_overlay_set(PixbufRenderer *pr, gint id, GdkPixbuf *pixbuf, gint x, gint y){ OverlayData *od; g_return_if_fail(IS_PIXBUF_RENDERER(pr)); od = pr_overlay_find(pr, id); if (!od) return; if (pixbuf) { pr_overlay_queue_draw(pr, od, TRUE); g_object_ref(G_OBJECT(pixbuf)); g_object_unref(G_OBJECT(od->pixbuf)); od->pixbuf = pixbuf; od->x = x; od->y = y; pr_overlay_queue_draw(pr, od, FALSE); } else { pr_overlay_queue_draw(pr, od, TRUE); pr_overlay_free(pr, od); }}gint pixbuf_renderer_overlay_get(PixbufRenderer *pr, gint id, GdkPixbuf **pixbuf, gint *x, gint *y){ OverlayData *od; g_return_val_if_fail(IS_PIXBUF_RENDERER(pr), FALSE); od = pr_overlay_find(pr, id); if (!od) return FALSE; if (pixbuf) *pixbuf = od->pixbuf; if (x) *x = od->x; if (y) *y = od->y; return TRUE;}void pixbuf_renderer_overlay_remove(PixbufRenderer *pr, gint id){ pixbuf_renderer_overlay_set(pr, id, NULL, 0, 0);}/* *------------------------------------------------------------------- * scroller overlay *------------------------------------------------------------------- */static gboolean pr_scroller_update_cb(gpointer data){ PixbufRenderer *pr = data; gint x, y; gint xinc, yinc; /* this was a simple scroll by difference between scroller and mouse position, * but all this math results in a smoother result and accounts for a dead zone. */ if (abs(pr->scroller_xpos - pr->scroller_x) < PR_SCROLLER_DEAD_ZONE) { x = 0; } else { gint shift = PR_SCROLLER_DEAD_ZONE / 2 * PR_SCROLLER_UPDATES_PER_SEC; x = (pr->scroller_xpos - pr->scroller_x) / 2 * PR_SCROLLER_UPDATES_PER_SEC; x += (x > 0) ? -shift : shift; } if (abs(pr->scroller_ypos - pr->scroller_y) < PR_SCROLLER_DEAD_ZONE) { y = 0; } else { gint shift = PR_SCROLLER_DEAD_ZONE / 2 * PR_SCROLLER_UPDATES_PER_SEC; y = (pr->scroller_ypos - pr->scroller_y) / 2 * PR_SCROLLER_UPDATES_PER_SEC; y += (y > 0) ? -shift : shift; } if (abs(x) < PR_SCROLLER_DEAD_ZONE * PR_SCROLLER_UPDATES_PER_SEC) { xinc = x; } else { xinc = pr->scroller_xinc; if (x >= 0) { if (xinc < 0) xinc = 0; if (x < xinc) xinc = x; if (x > xinc) xinc = MIN(xinc + x / PR_SCROLLER_UPDATES_PER_SEC, x); } else { if (xinc > 0) xinc = 0; if (x > xinc) xinc = x; if (x < xinc) xinc = MAX(xinc + x / PR_SCROLLER_UPDATES_PER_SEC, x); } } if (abs(y) < PR_SCROLLER_DEAD_ZONE * PR_SCROLLER_UPDATES_PER_SEC) { yinc = y; } else { yinc = pr->scroller_yinc; if (y >= 0) { if (yinc < 0) yinc = 0; if (y < yinc) yinc = y; if (y > yinc) yinc = MIN(yinc + y / PR_SCROLLER_UPDATES_PER_SEC, y); } else { if (yinc > 0) yinc = 0; if (y > yinc) yinc = y; if (y < yinc) yinc = MAX(yinc + y / PR_SCROLLER_UPDATES_PER_SEC, y); } } pr->scroller_xinc = xinc; pr->scroller_yinc = yinc; xinc = xinc / PR_SCROLLER_UPDATES_PER_SEC; yinc = yinc / PR_SCROLLER_UPDATES_PER_SEC; pixbuf_renderer_scroll(pr, xinc, yinc); return TRUE;}static void pr_scroller_timer_set(PixbufRenderer *pr, gint start){ if (pr->scroller_id != -1) { g_source_remove(pr->scroller_id); pr->scroller_id = -1; } if (start) { pr->scroller_id = g_timeout_add(1000 / PR_SCROLLER_UPDATES_PER_SEC, pr_scroller_update_cb, pr); }}static void pr_scroller_start(PixbufRenderer *pr, gint x, gint y){ if (pr->scroller_overlay == -1) { GdkPixbuf *pixbuf; gint w, h;#ifdef GQVIEW_BUILD pixbuf = pixbuf_inline(PIXBUF_INLINE_SCROLLER);#else pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 32, 32); gdk_pixbuf_fill(pixbuf, 0x000000ff);#endif w = gdk_pixbuf_get_width(pixbuf); h = gdk_pixbuf_get_height(pixbuf); pr->scroller_overlay = pixbuf_renderer_overlay_add(pr, pixbuf, x - w / 2, y - h / 2, FALSE, TRUE); g_object_unref(pixbuf); } pr->scroller_x = x; pr->scroller_y = y; pr->scroller_xpos = x; pr->scroller_ypos = y; pr_scroller_timer_set(pr, TRUE);}static void pr_scroller_stop(PixbufRenderer *pr){ if (pr->scroller_id == -1) return; pixbuf_renderer_overlay_remove(pr, pr->scroller_overlay); pr->scroller_overlay = -1; pr_scroller_timer_set(pr, FALSE);}/* *------------------------------------------------------------------- * borders *------------------------------------------------------------------- */static void pr_border_draw(PixbufRenderer *pr, gint x, gint y, gint w, gint h){ GtkWidget *box; gint rx, ry, rw, rh; box = GTK_WIDGET(pr); if (!box->window) return; if (!pr->pixbuf && !pr->source_tiles_enabled) { if (pr_clip_region(x, y, w, h, 0, 0, pr->window_width, pr->window_height, &rx, &ry, &rw, &rh)) { gdk_window_clear_area(box->window, rx, ry, rw, rh); pr_overlay_draw(pr, rx, ry, rw, rh); } return; } if (pr->vis_width < pr->window_width) { if (pr->x_offset > 0 && pr_clip_region(x, y, w, h, 0, 0, pr->x_offset, pr->window_height, &rx, &ry, &rw, &rh)) { gdk_window_clear_area(box->window, rx, ry, rw, rh); pr_overlay_draw(pr, rx, ry, rw, rh); } if (pr->window_width - pr->vis_width - pr->x_offset > 0 && pr_clip_region(x, y, w, h, pr->x_offset + pr->vis_width, 0, pr->window_width - pr->vis_width - pr->x_offset, pr->window_height, &rx, &ry, &rw, &rh)) { gdk_window_clear_area(box->window, rx, ry, rw, rh); pr_overlay_draw(pr, rx, ry, rw, rh); } } if (pr->vis_height < pr->window_height) { if (pr->y_offset > 0 && pr_clip_region(x, y, w, h, pr->x_offset, 0, pr->vis_width, pr->y_offset, &rx, &ry, &rw, &rh)) { gdk_window_clear_area(box->window, rx, ry, rw, rh); pr_overlay_draw(pr, rx, ry, rw, rh); } if (pr->window_height - pr->vis_height - pr->y_offset > 0 && pr_clip_region(x, y, w, h, pr->x_offset, pr->y_offset + pr->vis_height, pr->vis_width, pr->window_height - pr->vis_height - pr->y_offset, &rx, &ry, &rw, &rh)) { gdk_window_clear_area(box->window, rx, ry, rw, rh); pr_overlay_draw(pr, rx, ry, rw, rh); } }}static void pr_border_clear(PixbufRenderer *pr){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -