diff --git a/AUTHORS b/AUTHORS index 66053cf..d403b92 100644 --- a/AUTHORS +++ b/AUTHORS @@ -13,3 +13,4 @@ boris (Chris Ross) Martin Grimm Matt McClanahan Steve Langasek +Christophe Tronche diff --git a/src/Imlib2.h b/src/Imlib2.h index edfedd0..59e45f2 100644 --- a/src/Imlib2.h +++ b/src/Imlib2.h @@ -208,6 +208,9 @@ extern "C" Imlib_Image imlib_create_image_from_drawable(Pixmap mask, int x, int y, int width, int height, char need_to_grab_x); + Imlib_Image imlib_create_image_from_ximage(XImage *image, XImage *mask, int x, int y, + int width, int height, + char need_to_grab_x); Imlib_Image imlib_create_scaled_image_from_drawable(Pixmap mask, int source_x, int source_y, diff --git a/src/api.c b/src/api.c index 108d53d..6ea06a2 100644 --- a/src/api.c +++ b/src/api.c @@ -695,7 +695,10 @@ imlib_image_set_format(const char *format) CAST_IMAGE(im, ctxt_image); if (im->format) free(im->format); - im->format = strdup(format); + if (format) + im->format = strdup(format); + else + im->format = NULL; if (!(im->flags & F_FORMAT_IRRELEVANT)) { __imlib_DirtyImage(im); @@ -1006,6 +1009,24 @@ imlib_create_image_from_drawable(Pixmap mask, int x, int y, int width, return (Imlib_Image) im; } +Imlib_Image +imlib_create_image_from_ximage(XImage *image, XImage *mask, int x, int y, int width, + int height, char need_to_grab_x) +{ + ImlibImage *im; + char domask = 0; + + if (mask) + domask = 1; + im = __imlib_CreateImage(width, height, NULL); + im->data = malloc(width * height * sizeof(DATA32)); + __imlib_GrabXImageToRGBA(im->data, 0, 0, width, height, + ctxt_display, image, mask, ctxt_visual, + ctxt_depth, x, y, + width, height, need_to_grab_x); + return (Imlib_Image) im; +} + Imlib_Image imlib_create_scaled_image_from_drawable(Pixmap mask, int source_x, int source_y, int source_width, diff --git a/src/grab.c b/src/grab.c index b7c4990..f0ecc72 100644 --- a/src/grab.c +++ b/src/grab.c @@ -17,6 +17,308 @@ Tmp_HandleXError(Display * d, XErrorEvent * ev) _x_err = 1; } +void +__imlib_GrabXImageToRGBA(DATA32 *data, int ox, int oy, int ow, int oh, + Display *d, XImage *xim, XImage *mxim, Visual *v, + int depth, int x, int y, + int w, int h, char grab) +{ + int inx, iny; + DATA32 *src, *ptr; + int pixel, mpixel; + DATA8 rtab[256], gtab[256], btab[256]; + int origx, origy; + int bgr = 0; + + if (!data) return; + + if (grab) XGrabServer(d); /* This may prevent the image to be changed under our feet */ + origx = x; + origy = y; + + if (v->blue_mask > v->red_mask) bgr = 1; + + if (origx < 0) + inx = -origx; + else + inx = ox; + if (origy < 0) + iny = -origy; + else + iny = oy; + /* go thru the XImage and convert */ + if (xim->bits_per_pixel == 32) depth = 32; + switch (depth) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + if (mxim) { + for (y = 0; y < h; y++) { + ptr = data + ((y + iny) * ow) + inx; + for (x = 0; x < w; x++) { + pixel = XGetPixel(xim, x, y); + mpixel = XGetPixel(mxim, x, y); + *ptr++ = (0xff000000 >> (mpixel << 31)) | + (btab[pixel & 0xff]) | + (gtab[pixel & 0xff] << 8) | + (rtab[pixel & 0xff] << 16); + + } + } + } + else { + for (y = 0; y < h; y++) { + ptr = data + ((y + iny) * ow) + inx; + for (x = 0; x < w; x++) { + pixel = XGetPixel(xim, x, y); + *ptr++ = 0xff000000 | + (btab[pixel & 0xff]) | + (gtab[pixel & 0xff] << 8) | + (rtab[pixel & 0xff] << 16); + } + } + } + break; + case 16: +#undef MP +#undef RMSK +#undef GMSK +#undef BMSK +#undef R1SH +#undef G1SH +#undef B1SH +#undef R2SH +#undef G2SH +#undef B2SH +#undef P1 +#undef P2 +#define MP(x, y) (0xff000000 >> (XGetPixel(mxim, (x), (y)) << 31)) +#define RMSK 0xf80000 +#define GMSK 0x00fc00 +#define BMSK 0x0000f8 +#define R1SH(p) ((p) << 8) +#define G1SH(p) ((p) << 5) +#define B1SH(p) ((p) << 3) +#define R2SH(p) ((p) >> 8) +#define G2SH(p) ((p) >> 11) +#define B2SH(p) ((p) >> 13) +#define P1(p) (R1SH(p) & RMSK) | (G1SH(p) & GMSK) | (B1SH(p) & BMSK) +#define P2(p) (R2SH(p) & RMSK) | (G2SH(p) & GMSK) | (B2SH(p) & BMSK) + if (mxim) { + for (y = 0; y < h; y++) { + src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); + ptr = data + ((y + iny) * ow) + inx; + for (x = 0; x < (w - 1); x += 2) { + *ptr++ = MP(x, y) | P1(*src); + *ptr++ = MP(x + 1, y) | P2(*src); + src++; + } + if (x == (w - 1)) { + pixel = XGetPixel(xim, x, y); + *ptr++ = MP(x, y) | P1(pixel); + } + } + } +#undef MP +#define MP(x, y) (0xff000000) + else { + for (y = 0; y < h; y++) { + src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); + ptr = data + ((y + iny) * ow) + inx; + for (x = 0; x < (w - 1); x += 2) { + *ptr++ = MP(x, y) | P1(*src); + *ptr++ = MP(x + 1, y) | P2(*src); + src++; + } + if (x == (w - 1)) { + pixel = XGetPixel(xim, x, y); + *ptr++ = MP(x, y) | P1(pixel); + } + } + } + break; + case 15: +#undef MP +#undef RMSK +#undef GMSK +#undef BMSK +#undef R1SH +#undef G1SH +#undef B1SH +#undef R2SH +#undef G2SH +#undef B2SH +#undef P1 +#undef P2 +#define MP(x, y) (0xff000000 >> (XGetPixel(mxim, (x), (y)) << 31)) +#define RMSK 0xf80000 +#define GMSK 0x00f800 +#define BMSK 0x0000f8 +#define R1SH(p) ((p) << 9) +#define G1SH(p) ((p) << 6) +#define B1SH(p) ((p) << 3) +#define R2SH(p) ((p) >> 7) +#define G2SH(p) ((p) >> 10) +#define B2SH(p) ((p) >> 13) +#define P1(p) (R1SH(p) & RMSK) | (G1SH(p) & GMSK) | (B1SH(p) & BMSK) +#define P2(p) (R2SH(p) & RMSK) | (G2SH(p) & GMSK) | (B2SH(p) & BMSK) + if (mxim) { + for (y = 0; y < h; y++) { + src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); + ptr = data + ((y + iny) * ow) + inx; + for (x = 0; x < (w - 1); x += 2) { + *ptr++ = MP(x, y) | P1(*src); + *ptr++ = MP(x + 1, y) | P2(*src); + src++; + } + if (x == (w - 1)) { + pixel = XGetPixel(xim, x, y); + *ptr++ = MP(x, y) | P1(pixel); + } + } + } +#undef MP +#define MP(x, y) (0xff000000) + else { + for (y = 0; y < h; y++) { + src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); + ptr = data + ((y + iny) * ow) + inx; + for (x = 0; x < (w - 1); x += 2) { + *ptr++ = MP(x, y) | P1(*src); + *ptr++ = MP(x + 1, y) | P2(*src); + src++; + } + if (x == (w - 1)) { + pixel = XGetPixel(xim, x, y); + *ptr++ = MP(x, y) | P1(pixel); + } + } + } + break; + case 24: + if (bgr) { + if (mxim) { + for (y = 0; y < h; y++) { + ptr = data + ((y + iny) * ow) + inx; + for (x = 0; x < w; x++) { + pixel = XGetPixel(xim, x, y); + pixel = + ((pixel << 16) & 0xff0000) | + ((pixel) & 0x00ff00) | + ((pixel >> 16) & 0x0000ff); + mpixel = XGetPixel(mxim, x, y); + *ptr++ = (0xff000000 >> (mpixel << 31)) | + (pixel & 0x00ffffff); + } + } + } + else { + for (y = 0; y < h; y++) { + ptr = data + ((y + iny) * ow) + inx; + for (x = 0; x < w; x++) { + pixel = XGetPixel(xim, x, y); + *ptr++ = 0xff000000 | + ((pixel << 16) & 0xff0000) | + ((pixel) & 0x00ff00) | + ((pixel >> 16) & 0x0000ff); + } + } + } + } + else { + if (mxim) { + for (y = 0; y < h; y++) { + ptr = data + ((y + iny) * ow) + inx; + for (x = 0; x < w; x++) { + pixel = XGetPixel(xim, x, y); + mpixel = XGetPixel(mxim, x, y); + *ptr++ = (0xff000000 >> (mpixel << 31)) | + (pixel & 0x00ffffff); + } + } + } + else { + for (y = 0; y < h; y++) { + ptr = data + ((y + iny) * ow) + inx; + for (x = 0; x < w; x++) { + pixel = XGetPixel(xim, x, y); + *ptr++ = 0xff000000 | + (pixel & 0x00ffffff); + } + } + } + } + break; + case 32: + if (bgr) { + if (mxim) { + for (y = 0; y < h; y++) { + src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); + ptr = data + ((y + iny) * ow) + inx; + for (x = 0; x < w; x++) { + mpixel = XGetPixel(mxim, x, y); + pixel = + ((*src << 16) & 0xff0000) | + ((*src) & 0x00ff00) | + ((*src >> 16) & 0x0000ff); + *ptr++ = (0xff000000 >> (mpixel << 31)) | + ((pixel) & 0x00ffffff); + src++; + } + } + } + else { + for (y = 0; y < h; y++) { + src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); + ptr = data + ((y + iny) * ow) + inx; + for (x = 0; x < w; x++) { + *ptr++ = 0xff000000 | + ((*src << 16) & 0xff0000) | + ((*src) & 0x00ff00) | + ((*src >> 16) & 0x0000ff); + src++; + } + } + } + } + else { + if (mxim) { + for (y = 0; y < h; y++) { + src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); + ptr = data + ((y + iny) * ow) + inx; + for (x = 0; x < w; x++) { + mpixel = XGetPixel(mxim, x, y); + *ptr++ = (0xff000000 >> (mpixel << 31)) | + ((*src) & 0x00ffffff); + src++; + } + } + } + else { + for (y = 0; y < h; y++) { + src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); + ptr = data + ((y + iny) * ow) + inx; + for (x = 0; x < w; x++) { + *ptr++ = 0xff000000 | + ((*src) & 0x00ffffff); + src++; + } + } + } + } + break; + default: + break; + } + XUngrabServer(d); +} + char __imlib_GrabDrawableToRGBA(DATA32 *data, int ox, int oy, int ow, int oh, Display *d, Drawable p, Pixmap m, Visual *v, @@ -26,21 +328,17 @@ __imlib_GrabDrawableToRGBA(DATA32 *data, int ox, int oy, int ow, int oh, XErrorHandler prev_erh = NULL; XWindowAttributes xatt, ratt; char is_pixmap = 0, created_mask = 0, is_shm = 0, is_mshm = 0; - int i, pixel, mpixel; - int src_x, src_y, src_w, src_h, origx, origy, origw, origh; - int width, height, clipx, clipy, inx, iny; + int i; + int src_x, src_y, src_w, src_h, origw, origh; + int width, height, clipx, clipy; XShmSegmentInfo shminfo, mshminfo; XImage *xim = NULL, *mxim = NULL; static char x_does_shm = -1; - char bgr = 0; - DATA32 *ptr; DATA8 rtab[256], gtab[256], btab[256]; XColor cols[256]; /* FIXME: oh isnt used - i wonder if there's a bug looming... */ oh = 0; - origx = x; - origy = y; origw = w; origh = h; if (grab) @@ -235,6 +533,7 @@ __imlib_GrabDrawableToRGBA(DATA32 *data, int ox, int oy, int ow, int oh, is_shm = 0; } } + XSetErrorHandler((XErrorHandler) prev_erh); if ((m) && (domask)) { @@ -350,343 +649,11 @@ __imlib_GrabDrawableToRGBA(DATA32 *data, int ox, int oy, int ow, int oh, btab[i] = cols[i].blue >> 8; } } - if (v->blue_mask > v->red_mask) - bgr = 1; - if (data) - { - DATA32 *src; + __imlib_GrabXImageToRGBA(data, ox, oy, ow, oh, + d, xim, mxim, v, + depth, x, y, + w, h, 0); - if (origx < 0) - inx = -origx; - else - inx = ox; - if (origy < 0) - iny = -origy; - else - iny = oy; - /* go thru the XImage and convert */ - if (xim->bits_per_pixel == 32) - depth = 32; - switch (depth) - { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - if (mxim) - { - for (y = 0; y < h; y++) - { - ptr = data + ((y + iny) * ow) + inx; - for (x = 0; x < w; x++) - { - pixel = XGetPixel(xim, x, y); - mpixel = XGetPixel(mxim, x, y); - *ptr++ = (0xff000000 >> (mpixel << 31)) | - (btab[pixel & 0xff]) | - (gtab[pixel & 0xff] << 8) | - (rtab[pixel & 0xff] << 16); - - } - } - } - else - { - for (y = 0; y < h; y++) - { - ptr = data + ((y + iny) * ow) + inx; - for (x = 0; x < w; x++) - { - pixel = XGetPixel(xim, x, y); - *ptr++ = 0xff000000 | - (btab[pixel & 0xff]) | - (gtab[pixel & 0xff] << 8) | - (rtab[pixel & 0xff] << 16); - } - } - } - break; - case 16: -#undef MP -#undef RMSK -#undef GMSK -#undef BMSK -#undef R1SH -#undef G1SH -#undef B1SH -#undef R2SH -#undef G2SH -#undef B2SH -#undef P1 -#undef P2 -#define MP(x, y) (0xff000000 >> (XGetPixel(mxim, (x), (y)) << 31)) -#define RMSK 0xf80000 -#define GMSK 0x00fc00 -#define BMSK 0x0000f8 -#define R1SH(p) ((p) << 8) -#define G1SH(p) ((p) << 5) -#define B1SH(p) ((p) << 3) -#define R2SH(p) ((p) >> 8) -#define G2SH(p) ((p) >> 11) -#define B2SH(p) ((p) >> 13) -#define P1(p) (R1SH(p) & RMSK) | (G1SH(p) & GMSK) | (B1SH(p) & BMSK) -#define P2(p) (R2SH(p) & RMSK) | (G2SH(p) & GMSK) | (B2SH(p) & BMSK) - if (mxim) - { - for (y = 0; y < h; y++) - { - src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); - ptr = data + ((y + iny) * ow) + inx; - for (x = 0; x < (w - 1); x += 2) - { - *ptr++ = MP(x, y) | P1(*src); - *ptr++ = MP(x + 1, y) | P2(*src); - src++; - } - if (x == (w - 1)) - { - pixel = XGetPixel(xim, x, y); - *ptr++ = MP(x, y) | P1(pixel); - } - } - } -#undef MP -#define MP(x, y) (0xff000000) - else - { - for (y = 0; y < h; y++) - { - src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); - ptr = data + ((y + iny) * ow) + inx; - for (x = 0; x < (w - 1); x += 2) - { - *ptr++ = MP(x, y) | P1(*src); - *ptr++ = MP(x + 1, y) | P2(*src); - src++; - } - if (x == (w - 1)) - { - pixel = XGetPixel(xim, x, y); - *ptr++ = MP(x, y) | P1(pixel); - } - } - } - break; - case 15: -#undef MP -#undef RMSK -#undef GMSK -#undef BMSK -#undef R1SH -#undef G1SH -#undef B1SH -#undef R2SH -#undef G2SH -#undef B2SH -#undef P1 -#undef P2 -#define MP(x, y) (0xff000000 >> (XGetPixel(mxim, (x), (y)) << 31)) -#define RMSK 0xf80000 -#define GMSK 0x00f800 -#define BMSK 0x0000f8 -#define R1SH(p) ((p) << 9) -#define G1SH(p) ((p) << 6) -#define B1SH(p) ((p) << 3) -#define R2SH(p) ((p) >> 7) -#define G2SH(p) ((p) >> 10) -#define B2SH(p) ((p) >> 13) -#define P1(p) (R1SH(p) & RMSK) | (G1SH(p) & GMSK) | (B1SH(p) & BMSK) -#define P2(p) (R2SH(p) & RMSK) | (G2SH(p) & GMSK) | (B2SH(p) & BMSK) - if (mxim) - { - for (y = 0; y < h; y++) - { - src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); - ptr = data + ((y + iny) * ow) + inx; - for (x = 0; x < (w - 1); x += 2) - { - *ptr++ = MP(x, y) | P1(*src); - *ptr++ = MP(x + 1, y) | P2(*src); - src++; - } - if (x == (w - 1)) - { - pixel = XGetPixel(xim, x, y); - *ptr++ = MP(x, y) | P1(pixel); - } - } - } -#undef MP -#define MP(x, y) (0xff000000) - else - { - for (y = 0; y < h; y++) - { - src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); - ptr = data + ((y + iny) * ow) + inx; - for (x = 0; x < (w - 1); x += 2) - { - *ptr++ = MP(x, y) | P1(*src); - *ptr++ = MP(x + 1, y) | P2(*src); - src++; - } - if (x == (w - 1)) - { - pixel = XGetPixel(xim, x, y); - *ptr++ = MP(x, y) | P1(pixel); - } - } - } - break; - case 24: - if (bgr) - { - if (mxim) - { - for (y = 0; y < h; y++) - { - ptr = data + ((y + iny) * ow) + inx; - for (x = 0; x < w; x++) - { - pixel = XGetPixel(xim, x, y); - pixel = - ((pixel << 16) & 0xff0000) | - ((pixel) & 0x00ff00) | - ((pixel >> 16) & 0x0000ff); - mpixel = XGetPixel(mxim, x, y); - *ptr++ = (0xff000000 >> (mpixel << 31)) | - (pixel & 0x00ffffff); - } - } - } - else - { - for (y = 0; y < h; y++) - { - ptr = data + ((y + iny) * ow) + inx; - for (x = 0; x < w; x++) - { - pixel = XGetPixel(xim, x, y); - *ptr++ = 0xff000000 | - ((pixel << 16) & 0xff0000) | - ((pixel) & 0x00ff00) | - ((pixel >> 16) & 0x0000ff); - } - } - } - } - else - { - if (mxim) - { - for (y = 0; y < h; y++) - { - ptr = data + ((y + iny) * ow) + inx; - for (x = 0; x < w; x++) - { - pixel = XGetPixel(xim, x, y); - mpixel = XGetPixel(mxim, x, y); - *ptr++ = (0xff000000 >> (mpixel << 31)) | - (pixel & 0x00ffffff); - } - } - } - else - { - for (y = 0; y < h; y++) - { - ptr = data + ((y + iny) * ow) + inx; - for (x = 0; x < w; x++) - { - pixel = XGetPixel(xim, x, y); - *ptr++ = 0xff000000 | - (pixel & 0x00ffffff); - } - } - } - } - break; - case 32: - if (bgr) - { - if (mxim) - { - for (y = 0; y < h; y++) - { - src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); - ptr = data + ((y + iny) * ow) + inx; - for (x = 0; x < w; x++) - { - mpixel = XGetPixel(mxim, x, y); - pixel = - ((*src << 16) & 0xff0000) | - ((*src) & 0x00ff00) | - ((*src >> 16) & 0x0000ff); - *ptr++ = (0xff000000 >> (mpixel << 31)) | - ((pixel) & 0x00ffffff); - src++; - } - } - } - else - { - for (y = 0; y < h; y++) - { - src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); - ptr = data + ((y + iny) * ow) + inx; - for (x = 0; x < w; x++) - { - *ptr++ = 0xff000000 | - ((*src << 16) & 0xff0000) | - ((*src) & 0x00ff00) | - ((*src >> 16) & 0x0000ff); - src++; - } - } - } - } - else - { - if (mxim) - { - for (y = 0; y < h; y++) - { - src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); - ptr = data + ((y + iny) * ow) + inx; - for (x = 0; x < w; x++) - { - mpixel = XGetPixel(mxim, x, y); - *ptr++ = (0xff000000 >> (mpixel << 31)) | - ((*src) & 0x00ffffff); - src++; - } - } - } - else - { - for (y = 0; y < h; y++) - { - src = (DATA32 *)(xim->data + (xim->bytes_per_line * y)); - ptr = data + ((y + iny) * ow) + inx; - for (x = 0; x < w; x++) - { - *ptr++ = 0xff000000 | - ((*src) & 0x00ffffff); - src++; - } - } - } - } - break; - default: - break; - } - } /* destroy the Ximage */ if (is_shm) { diff --git a/src/grab.h b/src/grab.h index 744c897..b5c9ae6 100644 --- a/src/grab.h +++ b/src/grab.h @@ -5,4 +5,9 @@ __imlib_GrabDrawableToRGBA(DATA32 *data, int ox, int oy, int ow, int oh, Display *d, Drawable p, Pixmap m, Visual *v, Colormap cm, int depth, int x, int y, int w, int h, char domask, char grab); +void +__imlib_GrabXImageToRGBA(DATA32 *data, int ox, int oy, int ow, int oh, + Display *d, XImage *xim, XImage *mxim, Visual *v, + int depth, int x, int y, + int w, int h, char grab); #endif diff --git a/test/bmtest.c b/test/bmtest.c index 494412c..17caabe 100644 --- a/test/bmtest.c +++ b/test/bmtest.c @@ -113,7 +113,7 @@ int main (int argc, char **argv) imlib_render_image_on_drawable(0, 0 ); im_bg = temp2; imlib_context_set_image(temp); - imlib_free_image_and_decache(); + imlib_free_image(); } return 0;