RImage *RRotateImage(RImage *image, float angle) { /* * Angle steps below this value would represent a rotation * of less than 1 pixel for a 4k wide image, so not worth * bothering the difference. That makes it a perfect * candidate for an Epsilon when trying to compare angle * to known values */ static const float min_usable_angle = 0.00699; angle = fmod(angle, 360.0); if (angle < 0.0) angle += 360.0; if (angle < min_usable_angle) { /* Rotate by 0 degree */ return RCloneImage(image); } else if ((angle > 90.0 - min_usable_angle) && (angle < 90.0 + min_usable_angle)) { return rotate_image_90(image); } else if ((angle > 180.0 - min_usable_angle) && (angle < 180.0 + min_usable_angle)) { return wraster_rotate_image_180(image); } else if ((angle > 270.0 - min_usable_angle) && (angle < 270.0 + min_usable_angle)) { return rotate_image_270(image); } else { return rotate_image_any(image, angle); } }
WMPixmap *WMCreateBlendedPixmapFromRImage(WMScreen * scrPtr, RImage * image, const RColor * color) { WMPixmap *pixPtr; RImage *copy; copy = RCloneImage(image); if (!copy) return NULL; RCombineImageWithColor(copy, color); pixPtr = WMCreatePixmapFromRImage(scrPtr, copy, 0); RReleaseImage(copy); return pixPtr; }
static void hideWorkspaceName(void *data) { WScreen *scr = (WScreen *) data; if (!scr->workspace_name_data || scr->workspace_name_data->count == 0 || time(NULL) > scr->workspace_name_data->timeout) { XUnmapWindow(dpy, scr->workspace_name); if (scr->workspace_name_data) { RReleaseImage(scr->workspace_name_data->back); RReleaseImage(scr->workspace_name_data->text); wfree(scr->workspace_name_data); scr->workspace_name_data = NULL; } scr->workspace_name_timer = NULL; } else { RImage *img = RCloneImage(scr->workspace_name_data->back); Pixmap pix; scr->workspace_name_timer = WMAddTimerHandler(WORKSPACE_NAME_FADE_DELAY, hideWorkspaceName, scr); RCombineImagesWithOpaqueness(img, scr->workspace_name_data->text, scr->workspace_name_data->count * 255 / 10); RConvertImage(scr->rcontext, img, &pix); RReleaseImage(img); XSetWindowBackgroundPixmap(dpy, scr->workspace_name, pix); XClearWindow(dpy, scr->workspace_name); XFreePixmap(dpy, pix); XFlush(dpy); scr->workspace_name_data->count--; } }
RImage* RRotateImage(RImage *image, float angle) { RImage *img; int nwidth, nheight; int x, y; int bpp = image->format == RRGBAFormat ? 4 : 3; angle = ((int)angle % 360) + (angle - (int)angle); if (angle == 0.0) { return RCloneImage(image); } else if (angle == 90.0) { nwidth = image->height; nheight = image->width; img = RCreateImage(nwidth, nheight, True); if (!img) { return NULL; } if (bpp == 3) { unsigned char *optr, *nptr; unsigned offs; offs = nwidth * 4; optr = image->data; nptr = img->data; for (x = 0; x < nwidth; x++) { nptr = img->data + x*4; for (y = nheight; y; y--) { nptr[0] = *optr++; nptr[1] = *optr++; nptr[2] = *optr++; nptr[3] = 255; nptr += offs; } } } else { unsigned *optr, *nptr; unsigned *p; optr = (unsigned*)image->data; p = (unsigned*)img->data; for (x = 0; x < nwidth; x++) { nptr = p++; for (y = nheight; y; y--) { *nptr = *optr++; nptr += nwidth; } } } } else if (angle == 180.0) { nwidth = image->width; nheight = image->height; img = RCreateImage(nwidth, nheight, True); if (!img) { return NULL; } if (bpp == 3) { unsigned char *optr, *nptr; optr = image->data; nptr = img->data + nwidth * nheight * 4 - 4; for (y = 0; y < nheight; y++) { for (x = 0; x < nwidth; x++) { nptr[0] = optr[0]; nptr[1] = optr[1]; nptr[2] = optr[2]; nptr[3] = 255; optr += 3; nptr -= 4; } } } else { unsigned *optr, *nptr; optr = (unsigned*)image->data; nptr = (unsigned*)img->data + nwidth * nheight - 1; for (y = nheight*nwidth-1; y >= 0; y--) { *nptr = *optr; optr++; nptr--; } } } else if (angle == 270.0) { nwidth = image->height; nheight = image->width; img = RCreateImage(nwidth, nheight, True); if (!img) { return NULL; } if (bpp == 3) { unsigned char *optr, *nptr; unsigned offs; offs = nwidth * 4; optr = image->data; nptr = img->data; for (x = 0; x < nwidth; x++) { nptr = img->data + x*4; for (y = nheight; y; y--) { nptr[0] = *optr++; nptr[1] = *optr++; nptr[2] = *optr++; nptr[3] = 255; nptr += offs; } } } else { unsigned *optr, *nptr; unsigned *p; optr = (unsigned*)image->data; p = (unsigned*)img->data + nwidth*nheight; for (x = 0; x < nwidth; x++) { nptr = p--; for (y = nheight; y; y--) { *nptr = *optr++; nptr -= nwidth; } } } } else { img = rotateImage(image, angle); } return img; }
static RImage *rotate_image_any(RImage *source, float angle) { (void) angle; puts("NOT FULLY IMPLEMENTED"); return RCloneImage(source); #if 0 RImage *img; int nwidth, nheight; int x1, y1; int x2, y2; int dx, dy; int xi, yi; int xx, yy; unsigned char *src, *dst; int dpr, dpru, p; /* only 180o for now */ if (angle > 180.0) angle -= 180.0; angle = (angle * PI) / 180.0; nwidth = ceil(abs(cos(angle) * image->width)) + ceil(abs(cos(PI / 2 - angle) * image->width)); nheight = ceil(abs(sin(angle) * image->height)) + ceil(abs(cos(PI / 2 - angle) * image->height)); img = RCreateImage(nwidth, nheight, True); if (!img) return NULL; src = image->data; dst = img->data; x1 = floor(abs(cos(PI / 2 - angle) * image->width)); y1 = 0; x2 = 0; y2 = floor(abs(sin(PI / 2 - angle) * image->width)); xx = floor(abs(cos(angle) * image->height)) - 1; yy = nheight - 1; printf("%ix%i, %i %i %i %i %i\n", nwidth, nheight, x1, y1, x2, y2, (int)((angle * 180.0) / PI)); dx = abs(x2 - x1); dy = abs(y2 - y1); if (x1 > x2) xi = -1; else xi = 1; if (y1 > y2) yi = -1; else yi = 1; if (dx >= dy) { dpr = dy << 1; dpru = dpr - (dx << 1); p = dpr - dx; while (dx-- >= 0) { copyLine(x1, y1, xx, yy, nwidth, image->format, dst, &src); /* calc next step */ if (p > 0) { x1 += xi; y1 += yi; xx += xi; yy += yi; p += dpru; } else { x1 += xi; xx += xi; p += dpr; } } } else { dpr = dx << 1; dpru = dpr - (dy << 1); p = dpr - dy; while (dy-- >= 0) { xx = abs(x1 * sin(angle * PI / 180.0)); yy = abs(y1 * cos(angle * PI / 180.0)); copyLine(x1, y1, xx, yy, nwidth, image->format, dst, &src); /* calc next step */ if (p > 0) { x1 += xi; y1 += yi; p += dpru; } else { y1 += yi; p += dpr; } } } return img; #endif }
RImage *RLoadImage(RContext * context, const char *file, int index) { RImage *image = NULL; int i; struct stat st; assert(file != NULL); if (RImageCacheSize < 0) { init_cache(); } if (RImageCacheSize > 0) { for (i = 0; i < RImageCacheSize; i++) { if (RImageCache[i].file && strcmp(file, RImageCache[i].file) == 0) { if (stat(file, &st) == 0 && st.st_mtime == RImageCache[i].last_modif) { RImageCache[i].last_use = time(NULL); return RCloneImage(RImageCache[i].image); } else { free(RImageCache[i].file); RImageCache[i].file = NULL; RReleaseImage(RImageCache[i].image); } } } } switch (identFile(file)) { case IM_ERROR: return NULL; case IM_UNKNOWN: RErrorCode = RERR_BADFORMAT; return NULL; case IM_XPM: image = RLoadXPM(context, file); break; #ifdef USE_TIFF case IM_TIFF: image = RLoadTIFF(file, index); break; #endif /* USE_TIFF */ #ifdef USE_PNG case IM_PNG: image = RLoadPNG(context, file); break; #endif /* USE_PNG */ #ifdef USE_JPEG case IM_JPEG: image = RLoadJPEG(context, file); break; #endif /* USE_JPEG */ #ifdef USE_GIF case IM_GIF: image = RLoadGIF(file, index); break; #endif /* USE_GIF */ case IM_PPM: image = RLoadPPM(file); break; default: RErrorCode = RERR_BADFORMAT; return NULL; } /* store image in cache */ if (RImageCacheSize > 0 && image && (RImageCacheMaxImage == 0 || RImageCacheMaxImage >= image->width * image->height)) { time_t oldest = time(NULL); int oldest_idx = 0; int done = 0; for (i = 0; i < RImageCacheSize; i++) { if (!RImageCache[i].file) { RImageCache[i].file = malloc(strlen(file) + 1); strcpy(RImageCache[i].file, file); RImageCache[i].image = RCloneImage(image); RImageCache[i].last_modif = st.st_mtime; RImageCache[i].last_use = time(NULL); done = 1; break; } else { if (oldest > RImageCache[i].last_use) { oldest = RImageCache[i].last_use; oldest_idx = i; } } } /* if no slot available, dump least recently used one */ if (!done) { free(RImageCache[oldest_idx].file); RReleaseImage(RImageCache[oldest_idx].image); RImageCache[oldest_idx].file = malloc(strlen(file) + 1); strcpy(RImageCache[oldest_idx].file, file); RImageCache[oldest_idx].image = RCloneImage(image); RImageCache[oldest_idx].last_modif = st.st_mtime; RImageCache[oldest_idx].last_use = time(NULL); } } return image; }