--- rxvt-unicode/src/xpm.C 2007/08/05 06:19:01 1.59 +++ rxvt-unicode/src/xpm.C 2007/08/06 22:42:05 1.60 @@ -143,9 +143,14 @@ } static inline void -make_clip_rectangle (int pos, int size, int target_size, short &clip_pos, unsigned short &clip_size) +make_clip_rectangle (int pos, int size, int target_size, int &clip_pos, int &clip_size) { - if (pos < 0) + if (size <= 0) + { /* special case - tiling */ + clip_pos = pos; + clip_size = target_size; + } + else if (pos < 0) { clip_pos = 0; clip_size = MIN (target_size, size + pos); @@ -353,24 +358,168 @@ } #ifdef HAVE_AFTERIMAGE -ASImage * -bgPixmap_t::resize_asim (rxvt_term *target, ASImage *background, XRectangle &dst_rect) +bool +bgPixmap_t::render_asim (rxvt_term *target, ASImage *background, ARGB32 background_tint) { - if (original_asim == NULL || target == NULL) - return NULL; + if (target == NULL) + return false; int target_width = (int)target->szHint.width; int target_height = (int)target->szHint.height; + int new_pmap_width = target_width, new_pmap_height = target_height; + ASImage *result = NULL; + + int x = 0; + int y = 0; int w = h_scale * target_width / 100; int h = v_scale * target_height / 100; - int x = make_align_position (h_align, target_width, w); - int y = make_align_position (v_align, target_height, h); - make_clip_rectangle (x, w, target_width, dst_rect.x, dst_rect.width); - make_clip_rectangle (y, h, target_height, dst_rect.y, dst_rect.height); + if (original_asim) + { + x = make_align_position (h_align, target_width, w > 0 ? w : (int)original_asim->width); + y = make_align_position (v_align, target_height, h > 0 ? h : (int)original_asim->height); + } + + int dst_x, dst_y; + int clip_width, clip_height; + + make_clip_rectangle (x, w, target_width, dst_x, clip_width); + make_clip_rectangle (y, h, target_height, dst_y, clip_height); /* TODO : actuall scaling code :) */ + if (dst_x >= target_width || dst_y >= target_height + || clip_width <= 0 || clip_height <= 0 || original_asim == NULL) + { + result = background; + dst_x = dst_y = 0; + if (background) + { + new_pmap_width = clip_width = background->width; + new_pmap_height = clip_height = background->height; + } + else + new_pmap_width = new_pmap_height = 0; + } + else + { + result = original_asim; + if ((w > 0 && w != original_asim->width) + || (h > 0 && h != original_asim->height)) + { + result = scale_asimage (target->asv, original_asim, + w > 0 ? w : original_asim->width, + h > 0 ? h : original_asim->height, + background ? ASA_ASImage : ASA_XImage, + 100, ASIMAGE_QUALITY_DEFAULT); + } + if (background == NULL) + {/* if tiling - pixmap has to be sized exactly as the image */ + if (h_scale == 0) + new_pmap_width = result->width; + if (v_scale == 0) + new_pmap_height = result->height; + } + else + {/* if blending background and image - pixmap has to be sized same as target window */ + ASImageLayer *layers = create_image_layers (2); + ASImage *merged_im = NULL; + + layers[0].im = background; + layers[0].clip_width = target_width; + layers[0].clip_height = target_height; + layers[0].tint = background_tint; + layers[1].im = result; + if (w <= 0) + {/* tile horizontally */ + layers[1].dst_x = dst_x - (int)result->width; + layers[1].clip_width = result->width; + } + else + {/* clip horizontally */ + layers[1].dst_x = dst_x; + layers[1].clip_width = clip_width; + } + if (h <= 0) + { + layers[1].dst_y = dst_y - (int)result->height; + layers[1].clip_height = result->height; + } + else + { + layers[1].dst_y = dst_y; + layers[1].clip_height = clip_height; + } + if (target->rs[Rs_blendtype]) + { + layers[1].merge_scanlines = blend_scanlines_name2func (target->rs[Rs_blendtype]); + if (layers[1].merge_scanlines == NULL) + layers[1].merge_scanlines = alphablend_scanlines; + } + ASImage *tmp = merge_layers (target->asv, layers, 2, target_width, target_height, + ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT); + if (tmp) + { + if (result != original_asim) + destroy_asimage (&result); + result = tmp; + dst_x = dst_y = 0; + clip_width = target_width; + clip_height = target_height; + } + free (layers); + } + } + + if (pixmap) + { + if (result == NULL + || pmap_width != new_pmap_width + || pmap_height != new_pmap_height + || pmap_depth != target->depth) + { + XFreePixmap (target->dpy, pixmap); + pixmap = None; + } + } + + if (result) + { + XGCValues gcv; + GC gc; + + /* create Pixmap */ + if (pixmap == None) + { + pixmap = XCreatePixmap (target->dpy, target->vt, new_pmap_width, new_pmap_height, target->depth); + pmap_width = new_pmap_width; + pmap_height = new_pmap_height; + pmap_depth = target->depth; + } + /* fill with background color ( if result's not completely overlapping it)*/ + gcv.foreground = target->pix_colors[Color_bg]; + gc = XCreateGC (target->dpy, target->vt, GCForeground, &gcv); + + if (dst_x > 0 || dst_y > 0 + || dst_x + clip_width < new_pmap_width + || dst_y + clip_height < new_pmap_height) + { + XFillRectangle (target->dpy, pixmap, gc, 0, 0, new_pmap_width, new_pmap_height); + } + /* put result on pixmap */ + asimage2drawable (target->asv, pixmap, result, gc, 0, 0, dst_x, dst_y, clip_width, clip_height, True); + + /* set target's background to pixmap */ + XSetWindowBackgroundPixmap (target->dpy, target->vt, pixmap); + + XFreeGC (target->dpy, gc); + } + else + { + /* set target background to a pixel */ + XSetWindowBackground (target->dpy, target->vt, target->pix_colors[Color_bg]); + } + return true; } #endif