/**
* @file render.c
* @author Joe Wingbermuehle
* @date 2005-2006
*
* @brief Functions to render icons using the XRender extension.
*
*/
#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
/** Determine if the render extension is available. */
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
}
/** Draw a scaled icon. */
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 || !icon->useRender) {
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
}
/** Create a scaled icon. */
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, yindex;
int x, y;
double scalex, scaley;
double srcx, srcy;
int imageLine;
int maskLine;
Assert(icon);
if(!haveRender || !icon->useRender) {
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;
yindex = (int)srcy * icon->image->width;
for(x = 0; x < width; x++) {
index = 4 * (yindex + (int)srcx);
alpha = icon->image->data[index];
color.red = icon->image->data[index + 1];
color.red |= color.red << 8;
color.green = icon->image->data[index + 2];
color.green |= color.green << 8;
color.blue = icon->image->data[index + 3];
color.blue |= color.blue << 8;
GetColor(&color);
XPutPixel(destImage, x, y, color.pixel);
destMask->data[maskLine + x] = alpha | (alpha << 8);
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;
}
syntax highlighted by Code2HTML, v. 0.9.1