--- rxvt-unicode/src/rxvtimg.C 2012/06/07 08:36:53 1.35 +++ rxvt-unicode/src/rxvtimg.C 2012/06/07 18:07:42 1.46 @@ -4,8 +4,8 @@ #if HAVE_IMG -rxvt_img::rxvt_img (rxvt_screen *screen, XRenderPictFormat *format, int x, int y, int width, int height) -: s(screen), x(x), y(y), w(width), h(height), format(format), repeat(RepeatNormal), +rxvt_img::rxvt_img (rxvt_screen *screen, XRenderPictFormat *format, int x, int y, int width, int height, int repeat) +: s(screen), x(x), y(y), w(width), h(height), format(format), repeat(repeat), pm(0), ref(0) { } @@ -116,9 +116,6 @@ pa.repeat = repeat; Picture pic = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa); - XRectangle clip = { -x, -y, min (w, ref->w), min (h, ref->h) }; - XRenderSetPictureClipRectangles (dpy, pic, 0, 0, &clip, 1); - return pic; } @@ -181,7 +178,7 @@ int size = max (rh, rv) * 2 + 1; double *kernel = (double *)malloc (size * sizeof (double)); XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); - rxvt_img *img = new rxvt_img (s, format, x, y, w, h); + rxvt_img *img = new rxvt_img (s, format, x, y, w, h, repeat); img->alloc (); Picture src = src_picture (); @@ -396,22 +393,54 @@ return new rxvt_img (*this); } + +static XRenderPictFormat * +find_alpha_format_for (Display *dpy, XRenderPictFormat *format) +{ + if (format->direct.alphaMask) + return format; // already has alpha + + // try to find a suitable alpha format, one bit alpha is enough for our purposes + if (format->type == PictTypeDirect) + for (int n = 0; XRenderPictFormat *f = XRenderFindFormat (dpy, 0, 0, n); ++n) + if (f->direct.alphaMask + && f->type == PictTypeDirect + && ecb_popcount32 (f->direct.redMask ) >= ecb_popcount32 (format->direct.redMask ) + && ecb_popcount32 (f->direct.greenMask) >= ecb_popcount32 (format->direct.greenMask) + && ecb_popcount32 (f->direct.blueMask ) >= ecb_popcount32 (format->direct.blueMask )) + return f; + + // should be a very good fallback + return XRenderFindStandardFormat (dpy, PictStandardARGB32); +} + rxvt_img * rxvt_img::reify () { if (x == 0 && y == 0 && w == ref->w && h == ref->h) return clone (); - rxvt_img *img = new rxvt_img (s, format, 0, 0, w, h); - img->alloc (); - Display *dpy = s->display->dpy; + bool alpha = !format->direct.alphaMask + && (x || y) + && repeat == RepeatNone; + + rxvt_img *img = new rxvt_img (s, alpha ? find_alpha_format_for (dpy, format) : format, 0, 0, w, h, repeat); + img->alloc (); + Picture src = src_picture (); Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0); - XRenderComposite (dpy, PictOpSrc, src, None, dst, x, y, 0, 0, 0, 0, w, h); - + if (alpha) + { + XRenderColor rc = { 0, 0, 0, 0 }; + XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 0, 0, w, h);//TODO: split into four fillrectangles + XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, -x, -y, ref->w, ref->h); + } + else + XRenderComposite (dpy, PictOpSrc, src, None, dst, x, y, 0, 0, 0, 0, w, h); + XRenderFreePicture (dpy, src); XRenderFreePicture (dpy, dst); @@ -423,12 +452,18 @@ { rxvt_img *img = clone (); - //TODO: width > w, must reify - img->x += x; img->y += y; - img->w = width; - img->h = height; + + if (w != width || h != height) + { + img->w = width; + img->h = height; + + rxvt_img *img2 = img->reify (); + delete img; + img = img2; + } return img; } @@ -436,7 +471,7 @@ rxvt_img * rxvt_img::transform (int new_width, int new_height, double matrix[9]) { - rxvt_img *img = new rxvt_img (s, format, 0, 0, new_width, new_height); + rxvt_img *img = new rxvt_img (s, format, 0, 0, new_width, new_height, repeat); img->alloc (); Display *dpy = s->display->dpy; @@ -449,8 +484,10 @@ for (int j = 0; j < 3; ++j) xfrm.matrix [i][j] = XDoubleToFixed (matrix [i * 3 + j]); - xfrm.matrix [0][2] += XDoubleToFixed (x);//TODO - xfrm.matrix [0][3] += XDoubleToFixed (y); +#if 0 + xfrm.matrix [0][2] -= XDoubleToFixed (x);//TODO + xfrm.matrix [1][2] -= XDoubleToFixed (y); +#endif XRenderSetPictureFilter (dpy, src, "good", 0, 0); XRenderSetPictureTransform (dpy, src, &xfrm); @@ -465,13 +502,24 @@ rxvt_img * rxvt_img::scale (int new_width, int new_height) { + if (w == new_width && h == new_height) + return clone (); + double matrix[9] = { w / (double)new_width, 0, 0, 0, h / (double)new_height, 0, 0, 0, 1 }; - return transform (new_width, new_height, matrix); + int old_repeat_mode = repeat; + repeat = RepeatPad; // not right, but xrender can't proeprly scale it seems + + rxvt_img *img = transform (new_width, new_height, matrix); + + repeat = old_repeat_mode; + img->repeat = repeat; + + return img; } rxvt_img * @@ -490,12 +538,12 @@ } rxvt_img * -rxvt_img::convert_to (XRenderPictFormat *new_format, const rxvt_color &bg) +rxvt_img::convert_format (XRenderPictFormat *new_format, const rxvt_color &bg) { if (new_format == format) return clone (); - rxvt_img *img = new rxvt_img (s, new_format, 0, 0, w, h); + rxvt_img *img = new rxvt_img (s, new_format, x, y, w, h, repeat); img->alloc (); Display *dpy = s->display->dpy; @@ -528,7 +576,7 @@ { rxvt_img *img2 = clone (); Display *dpy = s->display->dpy; - Picture src = src_picture (); + Picture src = img->src_picture (); Picture dst = XRenderCreatePicture (dpy, img2->pm, img2->format, 0, 0); Picture mask = create_xrender_mask (dpy, img->pm, False);