📄 imagerenderer.cpp
字号:
assert(inRect->width == fromRect->width); assert(inRect->height == fromRect->height); if (isNull()) return; if (!cached) cache(); if (alpha) { gdk_gc_set_clip_mask(context->gc, alpha); gdk_gc_set_clip_origin(context->gc, inRect->x - fromRect->x, inRect->y - fromRect->y); } int x, y, sw, sh, sx, sy; if (!context->clip || !alpha) { // no clip or clip but not alpha --> draw directly x = inRect->x; y = inRect->y; sx = fromRect->x; sy = fromRect->y; sw = fromRect->width; sh = fromRect->height; gdk_draw_drawable(context->drawable, context->gc, pixmap, sx, sy, x, y, sw, sh); } else { // gdk clipping doesn't work when alpha is set --> manual clipping GdkRegion* dst_region = gdk_region_rectangle(inRect); gdk_region_intersect(dst_region, context->clip); GdkRectangle* areas = 0; gint n_areas = 0; gdk_region_get_rectangles(dst_region, &areas, &n_areas); if (n_areas>0) { int i; for (i=0;i<n_areas;i++) { x = areas[i].x; y = areas[i].y; sx = fromRect->x + (x - inRect->x); // source offsets of the image rendering sy = fromRect->y + (y - inRect->y); // ie. how many pixels were skipped because of clip sw = areas[i].width; sh = areas[i].height; gdk_draw_drawable(context->drawable, context->gc, pixmap, sx, sy, x, y, sw, sh); } } if (areas) g_free(areas); // Gdk API doesn't say whether areas allocated regardless of the result or not gdk_region_destroy(dst_region); } if (alpha) { gdk_gc_set_clip_mask(context->gc, NULL); gdk_gc_set_clip_origin(context->gc, 0, 0); gdk_gc_set_clip_region(context->gc, context->clip); } if (animate_id) { static_cast<GdkXftContext*>(context)->regionExpiresAt(&timeout_moment, inRect); }}void ImageRenderer::stopAnimation(){ removeAnimateTimeout();}void ImageRenderer::tileInRect(GdkRectangle* r, int sx, int sy, CGContextRef context){ assert(r); assert(context); if (isNull()) return; int x, y, w,h; int sw = wantedSize.width; int sh = wantedSize.height; x = r->x; y = r->y; w = r->width; h = r->height; if (!tileCached) tileCache(); if (!alpha) { // special case without alpha, we can use tiling acceleration // (don't know if this makes a difference) // assume gdk clipping works. gdk_gc_set_tile(context->gc, pixmap); gdk_gc_set_fill(context->gc, GDK_TILED); // start copy from (sx,sy), destination (x,y) // tile origin is relative to dest. drawable gdk_gc_set_ts_origin(context->gc, x - sx, y - sy); gdk_draw_rectangle(context->drawable, context->gc, TRUE, x, y, w, h); gdk_gc_set_fill(context->gc, GDK_SOLID); } else { // with alpha, do tiling by hand gdk_gc_set_clip_mask(context->gc, alpha); // remaining width, height int rw,rh; // current x, .. y. current source x, .. y, .. width, .. height int cx, cy, csx, csy, csw,csh; cy = y; rh = h; csy = sy; csh = MIN(sh - sy, h); while ( csh > 0 ) { cx = x; csx = sx; csw = MIN(sw - sx, w); // draw row with height of csh pixels, width of w rw = w; while (csw > 0) { // draw csw x csh pixels gdk_gc_set_clip_origin(context->gc, cx - csx, cy - csy); gdk_draw_drawable(context->drawable, context->gc, pixmap, csx, csy, cx, cy, csw, csh); csx = 0; cx += csw; rw -= csw; csw = MIN(rw, sw); } csy = 0; cy += csh; rh -= csh; csh = MIN(rh, sh); } //restore old clip region gdk_gc_set_clip_mask(context->gc, NULL); gdk_gc_set_clip_origin(context->gc, 0, 0); // assume that clip origin is always 0,0 gdk_gc_set_clip_region(context->gc, context->clip); } if (animate_id) { static_cast<GdkXftContext*>(context)->regionExpiresAt(&timeout_moment, r); }}bool ImageRenderer::isNull(){ if (!pixbuf && !anim) return true; return false;}void ImageRenderer::increaseUseCount(){}void ImageRenderer::decreaseUseCount(){}void ImageRenderer::flushRasterCache(){ invalidate();}void ImageRenderer::animate(){ bool need_update = gdk_pixbuf_animation_iter_advance(iter, NULL); if (need_update) { invalidate(); pixbuf = gdk_pixbuf_animation_iter_get_pixbuf(iter); }}void ImageRenderer::installAnimateTimeout(){ removeAnimateTimeout(); gint timeout = gdk_pixbuf_animation_iter_get_delay_time(iter); // milliseconds if (timeout) { animate_id = g_timeout_add(timeout, (GSourceFunc)::anim_timeout, this); g_get_current_time(&timeout_moment); g_time_val_add(&timeout_moment, (timeout*1000)); // microseconds } }void ImageRenderer::removeAnimateTimeout(){ if (animate_id != 0) g_source_remove(animate_id); animate_id = 0;}void ImageRenderer::loaderClosed(){ if (!anim && !pixbuf) return; if (gdk_pixbuf_animation_is_static_image(anim)) { g_object_unref(anim); anim = 0; return; } iter = gdk_pixbuf_animation_get_iter(anim, NULL); if (gdk_pixbuf_animation_iter_get_delay_time(iter) <= 0) { g_object_unref(iter); g_object_unref(anim); anim = 0; iter = 0; return; } invalidate(); g_object_unref(pixbuf); pixbuf = 0; installAnimateTimeout();}void ImageRenderer::sizePrepared(int width, int height){ if (wantedSize.width == -1 && wantedSize.height == -1) { fillGdkRectangle(&wantedSize, 0, 0, width, height); return; } if (wantedSize.width == width && wantedSize.height == height) return; gdk_pixbuf_loader_set_size(loader, wantedSize.width, wantedSize.height);}void ImageRenderer::areaPrepared(){ if (!anim) { anim = gdk_pixbuf_loader_get_animation(loader); if (anim) g_object_ref(anim); if (pixbuf) g_object_unref(pixbuf); pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); if (pixbuf) g_object_ref(pixbuf); }}void ImageRenderer::areaUpdated(int x, int y, int w, int h){ invalidate(); }ImageRenderer* ImageRenderer::copy(){ ImageRenderer* r = new ImageRenderer(*this); return r;}void ImageRenderer::animateTimeout(){ animate_id = 0; animate(); installAnimateTimeout();}GdkPixbuf* ImageRenderer::handle() const{ if (iter) return gdk_pixbuf_animation_iter_get_pixbuf(iter); return pixbuf;}extern "C"{staticvoidarea_prepared(GdkPixbufLoader *loader, gpointer user_data){ ImageRenderer* d = static_cast<ImageRenderer*>(user_data); d->areaPrepared();}staticvoidarea_updated(GdkPixbufLoader *loader, gint arg1, gint arg2, gint arg3, gint arg4, gpointer user_data){ ImageRenderer* d = static_cast<ImageRenderer*>(user_data); d->areaUpdated(arg1,arg2,arg3,arg4);}staticvoidclosed(GdkPixbufLoader *loader,gpointer user_data){ ImageRenderer* d = static_cast<ImageRenderer*>(user_data); d->loaderClosed();}staticvoidsize_prepared(GdkPixbufLoader *loader, gint width, gint height, gpointer user_data){ ImageRenderer* d = static_cast<ImageRenderer*>(user_data); d->sizePrepared(width, height);}staticgbooleananim_timeout(gpointer user_data){ ImageRenderer* d = static_cast<ImageRenderer*>(user_data); d->animateTimeout(); return FALSE;}} // extern "C"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -