Пример #1
0
/** Create a scaled icon. */
ScaledIconNode *CreateScaledRenderIcon(IconNode *icon,
                                       int width, int height) {

   ScaledIconNode *result = NULL;

#ifdef USE_XRENDER

   XRenderPictFormat *fp;
   XColor color;
   GC maskGC;
   XImage *destImage;
   XImage *destMask;
   unsigned long alpha;
   int index, yindex;
   int x, y;
   int imageLine;
   int maskLine;

   Assert(icon);

   if(!haveRender || !icon->useRender) {
      return NULL;
   }

   result = Allocate(sizeof(ScaledIconNode));
   result->next = icon->nodes;
   icon->nodes = result;

   result->width = width;
   result->height = height;
   width = icon->image->width;
   height = icon->image->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;
   for(y = 0; y < height; y++) {
      yindex = y * icon->image->width;
      for(x = 0; x < width; x++) {

         index = 4 * (yindex + x);
         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;

         color.red = (color.red * alpha) >> 8;
         color.green = (color.green * alpha) >> 8;
         color.blue = (color.blue * alpha) >> 8;

         GetColor(&color);
         XPutPixel(destImage, x, y, color.pixel);
         destMask->data[maskLine + x] = alpha;

      }
      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 alpha picture. */
   fp = JXRenderFindStandardFormat(display, PictStandardA8);
   Assert(fp);
   result->alphaPicture = JXRenderCreatePicture(display, result->mask, fp,
                                                0, NULL);
   
   /* Create the render picture. */
   fp = JXRenderFindVisualFormat(display, rootVisual);
   Assert(fp);
   result->imagePicture = JXRenderCreatePicture(display, result->image, fp,
                                                0, NULL);

   /* Free unneeded pixmaps. */
   JXFreePixmap(display, result->image);
   result->image = None;
   JXFreePixmap(display, result->mask);
   result->mask = None;

#endif

   return result;

}
Пример #2
0
/** Get a scaled icon. */
ScaledIconNode *GetScaledIcon(IconNode *icon, long fg,
                              int rwidth, int rheight)
{

   XColor color;
   XImage *image;
   ScaledIconNode *np;
   GC maskGC;
   int x, y;
   int scalex, scaley;     /* Fixed point. */
   int srcx, srcy;         /* Fixed point. */
   int ratio;              /* Fixed point. */
   int nwidth, nheight;
   unsigned char *data;

   Assert(icon);
   Assert(icon->image);

   if(rwidth == 0) {
      rwidth = icon->image->width;
   }
   if(rheight == 0) {
      rheight = icon->image->height;
   }

   ratio = (icon->image->width << 16) / icon->image->height;
   nwidth = Min(rwidth, (rheight * ratio) >> 16);
   nheight = Min(rheight, (nwidth << 16) / ratio);
   nwidth = (nheight * ratio) >> 16;
   if(nwidth < 1) {
      nwidth = 1;
   }
   if(nheight < 1) {
      nheight = 1;
   }

   /* Check if this size already exists.
    * Note that XRender scales on the fly.
    */
   for(np = icon->nodes; np; np = np->next) {
#ifdef USE_XRENDER
      if(np->imagePicture != None) {
         np->width = nwidth;
         np->height = nheight;
         return np;
      }
#endif
      if(np->width == nwidth && np->height == nheight) {
         if(!icon->image->bitmap || np->fg == fg) {
            return np;
         }
      }
   }

   /* See if we can use XRender to create the icon. */
#ifdef USE_XRENDER
   if(haveRender) {
      np = CreateScaledRenderIcon(icon, fg, nwidth, nheight);

      /* Don't keep the image data around after creating the icon. */
      Release(icon->image->data);
      icon->image->data = NULL;

      return np;
   }
#endif

   /* Create a new ScaledIconNode the old-fashioned way. */
   np = Allocate(sizeof(ScaledIconNode));
   np->fg = fg;
   np->width = nwidth;
   np->height = nheight;
   np->next = icon->nodes;
#ifdef USE_XRENDER
   np->imagePicture = None;
#endif
   icon->nodes = np;

   /* Create a mask. */
   np->mask = JXCreatePixmap(display, rootWindow, nwidth, nheight, 1);
   maskGC = JXCreateGC(display, np->mask, 0, NULL);
   JXSetForeground(display, maskGC, 0);
   JXFillRectangle(display, np->mask, maskGC, 0, 0, nwidth, nheight);
   JXSetForeground(display, maskGC, 1);

   /* Create a temporary XImage for scaling. */
   image = JXCreateImage(display, rootVisual, rootDepth, ZPixmap, 0,
                         NULL, nwidth, nheight, 8, 0);
   image->data = Allocate(sizeof(unsigned long) * nwidth * nheight);

   /* Determine the scale factor. */
   scalex = (icon->image->width << 16) / nwidth;
   scaley = (icon->image->height << 16) / nheight;

   data = icon->image->data;
   srcy = 0;
   for(y = 0; y < nheight; y++) {
      const int yindex = (srcy >> 16) * icon->image->width;
      srcx = 0;
      for(x = 0; x < nwidth; x++) {
         if(icon->image->bitmap) {
            const int index = yindex + (srcx >> 16);
            const int offset = index >> 3;
            const int mask = 1 << (index & 7);
            if(data[offset] & mask) {
               JXDrawPoint(display, np->mask, maskGC, x, y);
               XPutPixel(image, x, y, fg);
            }
         } else {
            const int yindex = (srcy >> 16) * icon->image->width;
            const int index = 4 * (yindex + (srcx >> 16));
            color.red = data[index + 1];
            color.red |= color.red << 8;
            color.green = data[index + 2];
            color.green |= color.green << 8;
            color.blue = data[index + 3];
            color.blue |= color.blue << 8;
            GetColor(&color);
            XPutPixel(image, x, y, color.pixel);
            if(data[index] >= 128) {
               JXDrawPoint(display, np->mask, maskGC, x, y);
            }
         }
         srcx += scalex;
      }
      srcy += scaley;
   }