diff --git a/src/backend/x11.c b/src/backend/x11.c index 3fbc46c..e403b10 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -88,7 +88,7 @@ MwLL MwLLCreate(MwLL parent, int x, int y, int width, int height) { r->display = parent->display; p = parent->window; } - r->window = XCreateSimpleWindow(r->display, p, x, y, width, height, 0, 0, WhitePixel(r->display, XDefaultScreen(r->display))); + r->window = XCreateSimpleWindow(r->display, p, x, y, width, height, 0, 0, WhitePixel(r->display, DefaultScreen(r->display))); r->visual = get_visual_info(r->display); @@ -114,7 +114,7 @@ MwLL MwLLCreate(MwLL parent, int x, int y, int width, int height) { r->wm_delete = XInternAtom(r->display, "WM_DELETE_WINDOW", False); XSetWMProtocols(r->display, r->window, &r->wm_delete, 1); - r->gc = XCreateGC(r->display, r->window, 0, 0); + r->gc = XCreateGC(r->display, r->window, 0, NULL); create_pixmap(r); @@ -355,8 +355,9 @@ void MwLLSetTitle(MwLL handle, const char* title) { } MwLLPixmap MwLLCreatePixmap(MwLL handle, unsigned char* data, int width, int height) { - MwLLPixmap r = malloc(sizeof(*r)); - char* d = malloc(4 * width * height); + MwLLPixmap r = malloc(sizeof(*r)); + char* di = malloc(4 * width * height); + char* dm = malloc(4 * width * height); int y, x; int evbase, erbase; XWindowAttributes attr; @@ -367,32 +368,12 @@ MwLLPixmap MwLLCreatePixmap(MwLL handle, unsigned char* data, int width, int hei r->width = width; r->height = height; r->display = handle->display; - r->use_shm = XShmQueryExtension(handle->display) ? 1 : 0; r->data = malloc(sizeof(unsigned long) * width * height); r->use_render = XRenderQueryExtension(handle->display, &evbase, &erbase) ? 1 : 0; - r->use_render = 0; - /* FIXME */ - r->use_shm = 0; - - if(r->use_shm) { - r->image = XShmCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), r->depth, ZPixmap, NULL, &r->shm, width, height); - - r->shm.shmid = shmget(IPC_PRIVATE, r->image->bytes_per_line * height, IPC_CREAT | 0777); - if(r->shm.shmid == -1) { - XDestroyImage(r->image); - r->use_shm = 0; - } else { - free(d); - r->shm.shmaddr = d = r->image->data = shmat(r->shm.shmid, 0, 0); - r->shm.readOnly = False; - XShmAttach(handle->display, &r->shm); - } - } - if(!r->use_shm) { - r->image = XCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), r->depth, ZPixmap, 0, d, width, height, 32, width * 4); - } + r->image = XCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), r->depth, ZPixmap, 0, di, width, height, 32, width * 4); + r->mask = XCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), r->depth, ZPixmap, 0, dm, width, height, 32, width * 4); for(y = 0; y < height; y++) { for(x = 0; x < width; x++) { @@ -406,20 +387,23 @@ MwLLPixmap MwLLCreatePixmap(MwLL handle, unsigned char* data, int width, int hei *(unsigned long*)(&r->data[(y * width + x) * sizeof(unsigned long)]) = (px[3] << 24) | p; } } + for(y = 0; y < height; y++) { + for(x = 0; x < width; x++) { + if(data[(y * width + x) * 4 + 3]) { + XPutPixel(r->mask, x, y, 1); + } else { + XPutPixel(r->mask, x, y, 0); + } + } + } return r; } void MwLLDestroyPixmap(MwLLPixmap pixmap) { if(pixmap->image != NULL) { - if(pixmap->use_shm) { - XShmDetach(pixmap->display, &pixmap->shm); - } XDestroyImage(pixmap->image); - if(pixmap->use_shm) { - shmdt(pixmap->shm.shmaddr); - shmctl(pixmap->shm.shmid, IPC_RMID, 0); - } + XDestroyImage(pixmap->mask); free(pixmap->data); } @@ -429,12 +413,33 @@ void MwLLDestroyPixmap(MwLLPixmap pixmap) { void MwLLDrawPixmap(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { if(pixmap->image != NULL && pixmap->use_render) { Pixmap px = XCreatePixmap(handle->display, handle->window, pixmap->width, pixmap->height, pixmap->depth); + Pixmap mask = XCreatePixmap(handle->display, handle->window, rect->width, rect->height, 1); + Pixmap pxsrc = XCreatePixmap(handle->display, handle->window, rect->width, rect->height, pixmap->depth); + GC maskgc = XCreateGC(handle->display, mask, 0, NULL); XRenderPictFormat* format = XRenderFindStandardFormat(handle->display, PictStandardRGB24); XRenderPictureAttributes attr; Picture src, dest; XTransform m; double xsc = (double)pixmap->width / rect->width; double ysc = (double)pixmap->height / rect->height; + char* dm = malloc(rect->width * rect->height * 4); + XImage* destmask; + int y, x; + + destmask = XCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), 1, ZPixmap, 0, dm, rect->width, rect->height, 32, rect->width * 4); + + for(y = 0; y < (int)rect->height; y++) { + for(x = 0; x < (int)rect->width; x++) { + int sy = y * pixmap->height / rect->height; + int sx = x * pixmap->width / rect->width; + sy = (int)sy; + sx = (int)sx; + + XPutPixel(destmask, x, y, XGetPixel(pixmap->mask, sx, sy)); + } + } + + XPutImage(handle->display, mask, maskgc, destmask, 0, 0, 0, 0, rect->width, rect->height); m.matrix[0][0] = XDoubleToFixed(xsc); m.matrix[0][1] = XDoubleToFixed(0); @@ -450,31 +455,39 @@ void MwLLDrawPixmap(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { memset(&attr, 0, sizeof(attr)); - if(pixmap->use_shm) { - XShmPutImage(handle->display, px, handle->gc, pixmap->image, 0, 0, 0, 0, pixmap->width, pixmap->height, False); - } else { - XPutImage(handle->display, px, handle->gc, pixmap->image, 0, 0, 0, 0, pixmap->width, pixmap->height); - } + XPutImage(handle->display, px, handle->gc, pixmap->image, 0, 0, 0, 0, pixmap->width, pixmap->height); src = XRenderCreatePicture(handle->display, px, format, 0, &attr); - dest = XRenderCreatePicture(handle->display, handle->pixmap, format, 0, &attr); + dest = XRenderCreatePicture(handle->display, pxsrc, format, 0, &attr); XRenderSetPictureTransform(handle->display, src, &m); - XRenderComposite(handle->display, PictOpSrc, src, 0, dest, 0, 0, 0, 0, rect->x, rect->y, rect->width, rect->height); + XRenderComposite(handle->display, PictOpSrc, src, 0, dest, 0, 0, 0, 0, 0, 0, rect->width, rect->height); XRenderFreePicture(handle->display, src); XRenderFreePicture(handle->display, dest); - XFreePixmap(handle->display, px); - } else if(pixmap->image != NULL) { - int use_shm = XShmQueryExtension(handle->display) ? 1 : 0; - XImage* dest; - XShmSegmentInfo shm; - char* d = malloc(rect->width * rect->height * 4); - int y, x; + XSetClipMask(handle->display, handle->gc, mask); + XSetClipOrigin(handle->display, handle->gc, rect->x, rect->y); + XCopyArea(handle->display, pxsrc, handle->pixmap, handle->gc, 0, 0, rect->width, rect->height, rect->x, rect->y); + XSetClipMask(handle->display, handle->gc, None); - /* FIXME */ - use_shm = 0; + XDestroyImage(destmask); + + XFreeGC(handle->display, maskgc); + XFreePixmap(handle->display, mask); + XFreePixmap(handle->display, px); + XFreePixmap(handle->display, pxsrc); + } else if(pixmap->image != NULL) { + XImage* dest; + XImage* destmask; + Pixmap mask = XCreatePixmap(handle->display, handle->window, rect->width, rect->height, 1); + GC maskgc = XCreateGC(handle->display, mask, 0, NULL); + char* di = malloc(rect->width * rect->height * 4); + char* dm = malloc(rect->width * rect->height * 4); + int y, x; + + dest = XCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), pixmap->depth, ZPixmap, 0, di, rect->width, rect->height, 32, rect->width * 4); + destmask = XCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), 1, ZPixmap, 0, dm, rect->width, rect->height, 32, rect->width * 4); for(y = 0; y < (int)rect->height; y++) { for(x = 0; x < (int)rect->width; x++) { @@ -486,42 +499,25 @@ void MwLLDrawPixmap(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { sx = (int)sx; ipx = &pixmap->image->data[(pixmap->width * sy + sx) * (pixmap->image->bitmap_unit / 8)]; - opx = &d[(rect->width * y + x) * (pixmap->image->bitmap_unit / 8)]; + opx = &di[(rect->width * y + x) * (pixmap->image->bitmap_unit / 8)]; memcpy(opx, ipx, pixmap->image->bitmap_unit / 8); + + XPutPixel(destmask, x, y, XGetPixel(pixmap->mask, sx, sy)); } } - if(use_shm) { - dest = XShmCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), pixmap->depth, ZPixmap, NULL, &shm, rect->width, rect->height); - shm.shmid = shmget(IPC_PRIVATE, dest->bytes_per_line * rect->height, IPC_CREAT | 0777); - if(shm.shmid == -1) { - XDestroyImage(dest); - use_shm = 0; - } else { - free(d); - shm.shmaddr = d = dest->data = shmat(shm.shmid, 0, 0); - shm.readOnly = False; - XShmAttach(handle->display, &shm); - } - } - if(!use_shm) { - dest = XCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), pixmap->depth, ZPixmap, 0, d, rect->width, rect->height, 32, rect->width * 4); - } + XPutImage(handle->display, mask, maskgc, destmask, 0, 0, 0, 0, rect->width, rect->height); - if(use_shm) { - XShmPutImage(handle->display, handle->pixmap, handle->gc, dest, 0, 0, rect->x, rect->y, rect->width, rect->height, False); - } else { - XPutImage(handle->display, handle->pixmap, handle->gc, dest, 0, 0, rect->x, rect->y, rect->width, rect->height); - } + XSetClipMask(handle->display, handle->gc, mask); + XSetClipOrigin(handle->display, handle->gc, rect->x, rect->y); + XPutImage(handle->display, handle->pixmap, handle->gc, dest, 0, 0, rect->x, rect->y, rect->width, rect->height); + XSetClipMask(handle->display, handle->gc, None); - if(use_shm) { - XShmDetach(handle->display, &shm); - } XDestroyImage(dest); - if(use_shm) { - shmdt(shm.shmaddr); - shmctl(shm.shmid, IPC_RMID, 0); - } + XDestroyImage(destmask); + + XFreeGC(handle->display, maskgc); + XFreePixmap(handle->display, mask); } } diff --git a/src/backend/x11.h b/src/backend/x11.h index 2958d8f..0b2ec07 100644 --- a/src/backend/x11.h +++ b/src/backend/x11.h @@ -46,11 +46,10 @@ struct _MwLLPixmap { int depth; - int use_shm; - int use_render; - XShmSegmentInfo shm; - Display* display; - XImage* image; + int use_render; + Display* display; + XImage* image; + XImage* mask; }; #endif diff --git a/src/draw.c b/src/draw.c index 2755874..86a3d6b 100644 --- a/src/draw.c +++ b/src/draw.c @@ -620,7 +620,7 @@ MwLLPixmap MwLoadRaw(MwWidget handle, unsigned char* rgb, int width, int height) MwLLFreeColor(bg); - px = MwLLCreatePixmap(handle->lowlevel, out, width, height); + px = MwLLCreatePixmap(handle->lowlevel, rgb, width, height); free(out); @@ -715,7 +715,7 @@ MwLLPixmap MwLoadXPMEx(MwWidget handle, char** data, unsigned char* bgcolor) { return px; } -MwLLPixmap MwLoadXPM(MwWidget handle, char** data){ +MwLLPixmap MwLoadXPM(MwWidget handle, char** data) { unsigned char rgba[4]; memset(rgba, 0, 4);