aboutsummaryrefslogtreecommitdiff
path: root/src/render.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/render.c')
-rw-r--r--src/render.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/src/render.c b/src/render.c
new file mode 100644
index 0000000..d2d747e
--- /dev/null
+++ b/src/render.c
@@ -0,0 +1,226 @@
+/****************************************************************************
+ * Functions to render icons using the XRender extension.
+ * Copyright (C) 2005 Joe Wingbermuehle
+ ****************************************************************************/
+
+#include "jwm.h"
+#include "render.h"
+#include "icon.h"
+#include "image.h"
+#include "main.h"
+#include "color.h"
+#include "error.h"
+
+#ifdef USE_XRENDER
+static int haveRender = 0;
+#endif
+
+/****************************************************************************
+ ****************************************************************************/
+void QueryRenderExtension()
+{
+
+#ifdef USE_XRENDER
+ int event, error;
+ Bool rc;
+
+ rc = JXRenderQueryExtension(display, &event, &error);
+ if(rc == True) {
+ haveRender = 1;
+ Debug("render extension enabled");
+ } else {
+ haveRender = 0;
+ Debug("render extension disabled");
+ }
+
+ if(haveRender && rootDepth < 24) {
+ Warning("color depth is %d, disabling icon alpha channel", rootDepth);
+ haveRender = 0;
+ }
+
+#endif
+
+}
+
+/****************************************************************************
+ ****************************************************************************/
+int PutScaledRenderIcon(IconNode *icon, ScaledIconNode *node, Drawable d,
+ int x, int y)
+{
+
+#ifdef USE_XRENDER
+
+ Picture dest;
+ Picture source;
+ XRenderPictFormat *fp;
+ int width, height;
+
+ Assert(icon);
+
+ if(!haveRender) {
+ return 0;
+ }
+
+ source = node->imagePicture;
+ if(source != None) {
+
+ fp = JXRenderFindVisualFormat(display, rootVisual);
+ Assert(fp);
+
+ dest = JXRenderCreatePicture(display, d, fp, 0, NULL);
+
+ if(node->width == 0) {
+ width = icon->image->width;
+ } else {
+ width = node->width;
+ }
+ if(node->height == 0) {
+ height = icon->image->height;
+ } else {
+ height = node->height;
+ }
+
+ JXRenderComposite(display, PictOpOver, source, None, dest,
+ 0, 0, 0, 0, x, y, width, height);
+
+ JXRenderFreePicture(display, dest);
+
+ }
+
+ return 1;
+
+#else
+
+ return 0;
+
+#endif
+
+}
+
+/****************************************************************************
+ ****************************************************************************/
+ScaledIconNode *CreateScaledRenderIcon(IconNode *icon,
+ int width, int height) {
+
+ ScaledIconNode *result = NULL;
+
+#ifdef USE_XRENDER
+
+ XRenderPictureAttributes picAttributes;
+ XRenderPictFormat picFormat;
+ XRenderPictFormat *fp;
+ XColor color;
+ GC maskGC;
+ XImage *destImage;
+ XImage *destMask;
+ unsigned long alpha;
+ int index;
+ int x, y;
+ double scalex, scaley;
+ double srcx, srcy;
+ int imageLine;
+ int maskLine;
+
+ Assert(icon);
+
+ if(!haveRender) {
+ return NULL;
+ }
+
+ result = Allocate(sizeof(ScaledIconNode));
+ result->next = icon->nodes;
+ icon->nodes = result;
+
+ if(width == 0) {
+ width = icon->image->width;
+ }
+ if(height == 0) {
+ height = icon->image->height;
+ }
+ result->width = width;
+ result->height = height;
+
+ scalex = (double)icon->image->width / width;
+ scaley = (double)icon->image->height / height;
+
+ result->mask = JXCreatePixmap(display, rootWindow, width, height, 8);
+ maskGC = JXCreateGC(display, result->mask, 0, NULL);
+ result->image = JXCreatePixmap(display, rootWindow,
+ width, height, rootDepth);
+
+ destImage = JXCreateImage(display, rootVisual, rootDepth, ZPixmap, 0,
+ NULL, width, height, 8, 0);
+ destImage->data = Allocate(sizeof(unsigned long) * width * height);
+
+ destMask = JXCreateImage(display, rootVisual, 8, ZPixmap, 0,
+ NULL, width, height, 8, 0);
+ destMask->data = Allocate(width * height);
+
+ imageLine = 0;
+ maskLine = 0;
+ srcy = 0.0;
+ for(y = 0; y < height; y++) {
+ srcx = 0.0;
+ for(x = 0; x < width; x++) {
+
+ index = (int)srcy * icon->image->width + (int)srcx;
+ alpha = (icon->image->data[index] >> 24) & 0xFFUL;
+ color.red = ((icon->image->data[index] >> 16) & 0xFFUL) * 257;
+ color.green = ((icon->image->data[index] >> 8) & 0xFFUL) * 257;
+ color.blue = (icon->image->data[index] & 0xFFUL) * 257;
+
+ GetColor(&color);
+ XPutPixel(destImage, x, y, color.pixel);
+ destMask->data[maskLine + x] = alpha * 257;
+
+ srcx += scalex;
+
+ }
+ srcy += scaley;
+ imageLine += destImage->bytes_per_line;
+ maskLine += destMask->bytes_per_line;
+ }
+
+ /* Render the image data to the image pixmap. */
+ JXPutImage(display, result->image, rootGC, destImage, 0, 0, 0, 0,
+ width, height);
+ Release(destImage->data);
+ destImage->data = NULL;
+ JXDestroyImage(destImage);
+
+ /* Render the alpha data to the mask pixmap. */
+ JXPutImage(display, result->mask, maskGC, destMask, 0, 0, 0, 0,
+ width, height);
+ Release(destMask->data);
+ destMask->data = NULL;
+ JXDestroyImage(destMask);
+ JXFreeGC(display, maskGC);
+
+ /* Create the render picture. */
+ picFormat.type = PictTypeDirect;
+ picFormat.depth = 8;
+ picFormat.direct.alphaMask = 0xFF;
+ fp = JXRenderFindFormat(display,
+ PictFormatType | PictFormatDepth | PictFormatAlphaMask,
+ &picFormat, 0);
+ Assert(fp);
+ result->maskPicture = JXRenderCreatePicture(display, result->mask,
+ fp, 0, NULL);
+ picAttributes.alpha_map = result->maskPicture;
+ fp = JXRenderFindVisualFormat(display, rootVisual);
+ Assert(fp);
+ result->imagePicture = JXRenderCreatePicture(display, result->image,
+ fp, CPAlphaMap, &picAttributes);
+
+ /* Free unneeded pixmaps. */
+ JXFreePixmap(display, result->image);
+ result->image = None;
+ JXFreePixmap(display, result->mask);
+ result->mask = None;
+
+#endif
+
+ return result;
+
+}
+