This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository e16.

View the commit online.

commit 1cef4a1044086c1c559e6ab866284e5de5ae0a52
Author: Kim Woelders <[email protected]>
AuthorDate: Fri Dec 23 15:11:57 2022 +0100

    cursors: Rework cursor creation
    
    In non-ancient mode (i.e. using XRenderCreateCursor) this should be
    somewhat more efficient.
---
 src/cursors.c | 147 ++++++++++++++++++++++++++++++----------------------------
 src/eimage.c  |  42 +++++++++++++++++
 src/eimage.h  |   8 +++-
 3 files changed, 126 insertions(+), 71 deletions(-)

diff --git a/src/cursors.c b/src/cursors.c
index 0c48bcf3..03feee6e 100644
--- a/src/cursors.c
+++ b/src/cursors.c
@@ -25,9 +25,6 @@
 
 #include <X11/Xlib.h>
 #include <X11/cursorfont.h>
-#if USE_COMPOSITE
-#include <X11/extensions/Xrender.h>
-#endif
 
 #include "E.h"
 #include "conf.h"
@@ -35,6 +32,9 @@
 #include "emodule.h"
 #include "list.h"
 #include "xwin.h"
+#if USE_XRENDER
+#include "eimage.h"
+#endif
 
 struct _ecursor {
    dlist_t             list;
@@ -49,65 +49,96 @@ struct _ecursor {
 
 static              LIST_HEAD(cursor_list);
 
-#if USE_COMPOSITE
-/* Assuming we have XRenderCreateCursor (render >= 0.5) */
+#if !USE_XRENDER
+
 static              EX_Cursor
-ECreatePixmapCursor(EX_Pixmap cpmap, EX_Pixmap cmask, unsigned int w,
-		    unsigned int h, int xh, int yh, unsigned int fg,
-		    unsigned int bg)
+_ECursorCreateFromBitmapData(int w, int h, unsigned char *cdata,
+			     unsigned char *cmask, int xh, int yh,
+			     unsigned int fg, unsigned int bg)
 {
    EX_Cursor           curs;
-   EX_Picture          pict;
-   EX_SrvRegion        rgn1, rgn2;
-
-   /* Looks like the pmap (not mask) bits in all theme cursors are inverted.
-    * Fix by swapping fg and bg colors */
+   Pixmap              pmap, mask;
+   XColor              fgxc, bgxc;
 
-   pict = EPictureCreateBuffer(VROOT, w, h, 1, NULL);
+   curs = NoXID;
+   mask = NoXID;
 
-   /* Clear entirely (alpha = 0) */
-   EPictureFillRect(pict, 0, 0, w, h, 0);
+   pmap = XCreateBitmapFromData(disp, WinGetXwin(VROOT), (char *)cdata, w, h);
+   if (!pmap)
+      goto done;
 
-   /* Paint fg color where cmask bits are set */
-   rgn1 = ERegionCreateFromBitmap(cmask);
-   EPictureSetClip(pict, rgn1);
-   EPictureFillRect(pict, 0, 0, w, h, fg);
+   if (cmask)
+      mask =
+	 XCreateBitmapFromData(disp, WinGetXwin(VROOT), (char *)cmask, w, h);
 
-   /* Paint bg color where cpmap bits are set */
-   rgn2 = ERegionCreateFromBitmap(cpmap);
-   ERegionIntersect(rgn1, rgn2);
-   EPictureSetClip(pict, rgn1);
-   EPictureFillRect(pict, 0, 0, w, h, bg);
+   /* Looks like the pmap (not mask) bits in all theme cursors are inverted.
+    * Fix by swapping fg and bg colors. */
+   COLOR32_TO_RGB16(bg, fgxc.red, fgxc.green, fgxc.blue);
+   COLOR32_TO_RGB16(fg, bgxc.red, bgxc.green, bgxc.blue);
+   XAllocColor(disp, WinGetCmap(VROOT), &fgxc);
+   XAllocColor(disp, WinGetCmap(VROOT), &bgxc);
 
-   curs = XRenderCreateCursor(disp, pict, xh, yh);
+   curs = XCreatePixmapCursor(disp, pmap, mask, &fgxc, &bgxc, xh, yh);
 
-   ERegionDestroy(rgn1);
-   ERegionDestroy(rgn2);
-   EPictureDestroy(pict);
+   EFreePixmap(pmap);
+   if (mask)
+      EFreePixmap(mask);
 
+ done:
    return curs;
 }
-#else
+
+#endif /* !USE_XRENDER */
+
 static              EX_Cursor
-ECreatePixmapCursor(EX_Pixmap cpmap, EX_Pixmap cmask,
-		    unsigned int w __UNUSED__, unsigned int h __UNUSED__,
-		    int xh, int yh, unsigned int fg, unsigned int bg)
+_ECursorCreateFromBitmaps(const char *img, unsigned int fg, unsigned int bg)
 {
    EX_Cursor           curs;
-   XColor              fgxc, bgxc;
+   unsigned char      *cdata, *cmask;
+   unsigned int        w, h, wm, hm;
+   int                 xh, yh;
+   char                msk[FILEPATH_LEN_MAX];
+
+   curs = NoXID;
+   w = h = 0;
+   xh = yh = 0;
+   cdata = cmask = NULL;
+
+   XReadBitmapFileData(img, &w, &h, &cdata, &xh, &yh);
+   if (!cdata)
+      goto done;
+   XQueryBestCursor(disp, WinGetXwin(VROOT), w, h, &wm, &hm);
+   if (w > wm || h > hm)
+      goto done;
+
+   Esnprintf(msk, sizeof(msk), "%s.mask", img);
+   XReadBitmapFileData(msk, &wm, &hm, &cmask, NULL, NULL);
+   if (cmask && (w != wm || h != hm))
+     {
+	/* Dimension mismatch - drop mask */
+	XFree(cmask);
+	cmask = NULL;
+     }
 
-   /* Looks like the pmap (not mask) bits in all theme cursors are inverted.
-    * Fix by swapping fg and bg colors */
-   COLOR32_TO_RGB16(bg, fgxc.red, fgxc.green, fgxc.blue);
-   COLOR32_TO_RGB16(fg, bgxc.red, bgxc.green, bgxc.blue);
-   XAllocColor(disp, WinGetCmap(VROOT), &fgxc);
-   XAllocColor(disp, WinGetCmap(VROOT), &bgxc);
+   if (xh < 0 || xh >= (int)w)
+      xh = w / 2;
+   if (yh < 0 || yh >= (int)h)
+      yh = h / 2;
 
-   curs = XCreatePixmapCursor(disp, cpmap, cmask, &fgxc, &bgxc, xh, yh);
+#if USE_XRENDER
+   curs = EImageCursorCreateFromBitmapData(w, h, cdata, cmask, xh, yh, fg, bg);
+#else
+   curs = _ECursorCreateFromBitmapData(w, h, cdata, cmask, xh, yh, fg, bg);
+#endif
+
+   if (cmask)
+      XFree(cmask);
+ done:
+   if (cdata)
+      XFree(cdata);
 
    return curs;
 }
-#endif
 
 static void
 _ECursorCreate(const char *name, const char *image, int native_id,
@@ -155,10 +186,7 @@ _ECursorDestroy(ECursor * ec)
 static ECursor     *
 _ECursorRealize(ECursor * ec)
 {
-   Pixmap              pmap, mask;
-   int                 xh, yh;
-   unsigned int        w, h, ww, hh;
-   char               *img, msk[FILEPATH_LEN_MAX];
+   char               *img;
 
    if (ec->file)
      {
@@ -167,34 +195,13 @@ _ECursorRealize(ECursor * ec)
 	if (!img)
 	   goto done;
 
-	Esnprintf(msk, sizeof(msk), "%s.mask", img);
-	pmap = 0;
-	mask = 0;
-	xh = 0;
-	yh = 0;
-	XReadBitmapFile(disp, WinGetXwin(VROOT), msk, &w, &h, &mask, &xh, &yh);
-	XReadBitmapFile(disp, WinGetXwin(VROOT), img, &w, &h, &pmap, &xh, &yh);
-	XQueryBestCursor(disp, WinGetXwin(VROOT), w, h, &ww, &hh);
-	if ((w <= ww) && (h <= hh) && (pmap))
-	  {
-	     if (xh < 0 || xh >= (int)w)
-		xh = (int)w / 2;
-	     if (yh < 0 || yh >= (int)h)
-		yh = (int)h / 2;
-	     ec->cursor =
-		ECreatePixmapCursor(pmap, mask, w, h, xh, yh, ec->fg, ec->bg);
-	  }
-
+	ec->cursor = _ECursorCreateFromBitmaps(img, ec->fg, ec->bg);
 	if (ec->cursor == NoXID)
 	  {
-	     Eprintf("*** Failed to create cursor \"%s\" from %s,%s\n",
-		     ec->name, img, msk);
+	     Eprintf("*** Failed to create cursor \"%s\" from %s,%s.mask\n",
+		     ec->name, img, img);
 	  }
 
-	if (pmap)
-	   EFreePixmap(pmap);
-	if (mask)
-	   EFreePixmap(mask);
 	Efree(img);
      }
    else
diff --git a/src/eimage.c b/src/eimage.c
index 1299a8bd..56e4eae2 100644
--- a/src/eimage.c
+++ b/src/eimage.c
@@ -757,4 +757,46 @@ EImageDefineCursor(EImage * im, int xh, int yh)
    return curs;
 }
 
+EX_Cursor
+EImageCursorCreateFromBitmapData(int w, int h, const unsigned char *cdata,
+				 const unsigned char *cmask, int xh, int yh,
+				 unsigned int fg, unsigned int bg)
+{
+   EX_Cursor           curs;
+   uint32_t           *data, pixel;
+   int                 i, j;
+   Imlib_Image         im;
+
+   /* Looks like the pmap (not mask) bits in all theme cursors are inverted.
+    * Fix by swapping fg and bg colors. */
+
+   im = imlib_create_image(w, h);
+   imlib_context_set_image(im);
+   imlib_image_set_has_alpha(1);
+   data = ""
+
+   for (i = 0; i < h; i++)
+     {
+	for (j = 0; j < w; j++)
+	  {
+	     int                 ix = i * ((w + 7) / 8) + j / 8;
+	     int                 bit = j % 8, bits_i, bits_m;
+	     bits_i = cdata[ix];
+	     bits_m = cmask ? cmask[ix] : 0;
+	     if ((bits_m & (1 << bit)) == 0)
+		pixel = 0;
+	     else if (bits_i & (1 << bit))
+		pixel = bg;	/* fg/bg swapped */
+	     else
+		pixel = fg;
+	     *data++ = pixel;
+	  }
+     }
+
+   curs = EImageDefineCursor(im, xh, yh);
+   imlib_free_image_and_decache();
+
+   return curs;
+}
+
 #endif /* USE_XRENDER */
diff --git a/src/eimage.h b/src/eimage.h
index 53d59dd3..066413a0 100644
--- a/src/eimage.h
+++ b/src/eimage.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2021 Kim Woelders
+ * Copyright (C) 2004-2022 Kim Woelders
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
@@ -118,6 +118,12 @@ void                ScaleTile(Win wsrc, EX_Drawable src, Win wdst,
 			      int flags);
 
 EX_Cursor           EImageDefineCursor(EImage * im, int xh, int yh);
+EX_Cursor           EImageCursorCreateFromBitmapData(int w, int h,
+						     const unsigned char *cdata,
+						     const unsigned char *cmask,
+						     int xh, int yh,
+						     unsigned int fg,
+						     unsigned int bg);
 
 void                EDrawableDumpImage(EX_Drawable draw, const char *txt);
 

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to