--- rxvt-unicode/src/rxvtimg.C 2012/06/07 07:53:12 1.32 +++ rxvt-unicode/src/rxvtimg.C 2012/06/07 11:52:26 1.42 @@ -4,17 +4,16 @@ #if HAVE_IMG -rxvt_img::rxvt_img (rxvt_screen *screen, XRenderPictFormat *format, int width, int height) -: s(screen), x(0), y(0), w(width), h(height), format(format), repeat(RepeatNormal), - pm(0), refcnt(0) +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) { } rxvt_img::rxvt_img (const rxvt_img &img) -: s(img.s), x(img.x), y(img.y), w(img.w), h(img.h), format(img.format), repeat(img.repeat), pm(img.pm), refcnt(img.refcnt) +: s(img.s), x(img.x), y(img.y), w(img.w), h(img.h), format(img.format), repeat(img.repeat), pm(img.pm), ref(img.ref) { - if (refcnt) - ++*refcnt; + ++ref->cnt; } #if 0 @@ -46,11 +45,15 @@ rxvt_img *img = new rxvt_img ( s, XRenderFindVisualFormat (dpy, DefaultVisual (dpy, s->display->screen)), + 0, + 0, root_pm_w, root_pm_h ); img->pm = root_pixmap; + img->ref = new pixref (root_pm_w, root_pm_h); + img->ref->ours = false; return img; } @@ -67,6 +70,8 @@ rxvt_img *img = new rxvt_img ( s, XRenderFindStandardFormat (s->display->dpy, gdk_pixbuf_get_has_alpha (pb) ? PictStandardARGB32 : PictStandardRGB24), + 0, + 0, gdk_pixbuf_get_width (pb), gdk_pixbuf_get_height (pb) ); @@ -81,13 +86,13 @@ void rxvt_img::destroy () { - if (!refcnt || --*refcnt) + if (--ref->cnt) return; - if (pm) + if (pm && ref->ours) XFreePixmap (s->display->dpy, pm); - delete refcnt; + delete ref; } rxvt_img::~rxvt_img () @@ -99,24 +104,37 @@ rxvt_img::alloc () { pm = XCreatePixmap (s->display->dpy, s->display->root, w, h, format->depth); - refcnt = new int (1); + ref = new pixref (w, h); +} + +Picture +rxvt_img::src_picture () +{ + Display *dpy = s->display->dpy; + + XRenderPictureAttributes pa; + pa.repeat = repeat; + Picture pic = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa); + + return pic; } void rxvt_img::unshare () { - if (refcnt && *refcnt == 1) + if (ref->cnt == 1 && ref->ours) return; - Pixmap pm2 = XCreatePixmap (s->display->dpy, s->display->root, w, h, format->depth); + //TODO: maybe should reify instead + Pixmap pm2 = XCreatePixmap (s->display->dpy, s->display->root, ref->w, ref->h, format->depth); GC gc = XCreateGC (s->display->dpy, pm, 0, 0); - XCopyArea (s->display->dpy, pm, pm2, gc, 0, 0, w, h, 0, 0); + XCopyArea (s->display->dpy, pm, pm2, gc, 0, 0, ref->w, ref->h, 0, 0); XFreeGC (s->display->dpy, gc); destroy (); pm = pm2; - refcnt = new int (1); + ref = new pixref (ref->w, ref->h); } void @@ -160,13 +178,13 @@ 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, w, h); + rxvt_img *img = new rxvt_img (s, format, x, y, w, h, repeat); img->alloc (); - XRenderPictureAttributes pa; + Picture src = src_picture (); + XRenderPictureAttributes pa; pa.repeat = RepeatPad; - Picture src = XRenderCreatePicture (dpy, pm , format, CPRepeat, &pa); Picture dst = XRenderCreatePicture (dpy, img->pm, format, CPRepeat, &pa); Pixmap tmp_pm = XCreatePixmap (dpy, pm, w, h, format->depth); @@ -376,18 +394,31 @@ } rxvt_img * -rxvt_img::sub_rect (int x, int y, int width, int height) +rxvt_img::reify () { - rxvt_img *img = new rxvt_img (s, format, width, height); - img->alloc (); + if (x == 0 && y == 0 && w == ref->w && h == ref->h) + return clone (); Display *dpy = s->display->dpy; - XRenderPictureAttributes pa; - pa.repeat = repeat; - Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa); - Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0); - XRenderComposite (dpy, PictOpSrc, src, None, dst, x, y, 0, 0, 0, 0, width, height); + bool alpha = !format->direct.alphaMask + && (x || y) + && repeat == RepeatNone; + + rxvt_img *img = new rxvt_img (s, alpha ? XRenderFindStandardFormat (dpy, PictStandardARGB32) : format, 0, 0, w, h, repeat); + img->alloc (); + + Picture src = src_picture (); + Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0); + + if (alpha) + { + XRenderColor rc = { 0, 0, 0, 0 }; + XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 0, 0, w, h); + 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); @@ -396,16 +427,35 @@ } rxvt_img * +rxvt_img::sub_rect (int x, int y, int width, int height) +{ + rxvt_img *img = clone (); + + img->x += x; + img->y += y; + + if (w != width || h != height) + { + img->w = width; + img->h = height; + + rxvt_img *img2 = img->reify (); + delete img; + img = img2; + } + + return img; +} + +rxvt_img * rxvt_img::transform (int new_width, int new_height, double matrix[9]) { - rxvt_img *img = new rxvt_img (s, format, 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; - XRenderPictureAttributes pa; - pa.repeat = repeat; - Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa); - Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0); + Picture src = src_picture (); + Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0); XTransform xfrm; @@ -413,6 +463,9 @@ 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); + XRenderSetPictureFilter (dpy, src, "good", 0, 0); XRenderSetPictureTransform (dpy, src, &xfrm); XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, new_width, new_height); @@ -432,7 +485,15 @@ 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 * @@ -456,11 +517,13 @@ if (new_format == format) return clone (); - rxvt_img *img = new rxvt_img (s, new_format, w, h); + rxvt_img *img = new rxvt_img (s, new_format, 0, 0, w, h, repeat); img->alloc (); + printf ("convert %d to %d\n", format->direct.alphaMask, new_format->direct.alphaMask);//D + Display *dpy = s->display->dpy; - Picture src = XRenderCreatePicture (dpy, pm, format, 0, 0); + Picture src = src_picture (); Picture dst = XRenderCreatePicture (dpy, img->pm, new_format, 0, 0); int op = PictOpSrc; @@ -489,7 +552,7 @@ { rxvt_img *img2 = clone (); Display *dpy = s->display->dpy; - Picture src = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0); + Picture src = img->src_picture (); Picture dst = XRenderCreatePicture (dpy, img2->pm, img2->format, 0, 0); Picture mask = create_xrender_mask (dpy, img->pm, False);