tightvnc-1.3dev5-vncviewer-alpha-cursor.patch 3.66 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
--- vnc_unixsrc.orig/vncviewer/cursor.c	2003-01-15 04:46:52.000000000 -0500
+++ vnc_unixsrc/vncviewer/cursor.c	2005-02-05 12:28:10.000000000 -0500
@@ -472,6 +472,140 @@
   int offset, bytesPerPixel;
   char *pos;
 
+#define alphahack
+#ifdef alphahack
+  /* hack to have cursor transparency at 32bpp <runge@karlrunge.com> */
+  static int alphablend = -1;
+
+  if (alphablend < 0) {
+	/* you have to set NO_ALPHABLEND=1 in your environment to disable */
+	if (getenv("NO_ALPHABLEND")) {
+		alphablend = 0;
+	} else {
+		alphablend = 1;
+	}
+  }
+
+  bytesPerPixel = myFormat.bitsPerPixel / 8;
+
+  if (alphablend && bytesPerPixel == 4) {
+	unsigned long pixel, put, *upos, *upix;
+	int got_alpha = 0, rsX, rsY, rsW, rsH;
+	static XImage *image = NULL;
+	static int iwidth = 128;
+
+	if (! image) {
+		/* watch out for tiny fb (rare) */
+		if (iwidth > si.framebufferWidth) {
+			iwidth = si.framebufferWidth;
+		}
+		if (iwidth > si.framebufferHeight) {
+			iwidth = si.framebufferHeight;
+		}
+
+		/* initialize an XImage with a chunk of desktopWin */
+		image = XGetImage(dpy, desktopWin, 0, 0, iwidth, iwidth,
+		    AllPlanes, ZPixmap);
+	}
+
+	/* first check if there is any non-zero alpha channel data at all: */
+	for (y = 0; y < rcHeight; y++) {
+		for (x = 0; x < rcWidth; x++) {
+			int alpha;
+
+			offset = y * rcWidth + x;
+			pos = (char *)&rcSource[offset * bytesPerPixel];
+
+			upos = (unsigned long *) pos;
+			alpha = (*upos & 0xff000000) >> 24;
+			if (alpha) {
+				got_alpha = 1;
+				break;
+			}
+		}
+		if (got_alpha) {
+			break;
+		}
+	}
+
+	if (!got_alpha) {
+		/* no alpha channel data, fallback to the old way */
+		goto oldway;
+	}
+
+	/* load the saved fb patch in to image (faster way?) */
+	XGetSubImage(dpy, rcSavedArea, 0, 0, rcWidth, rcHeight,
+	    AllPlanes, ZPixmap, image, 0, 0);
+	upix = (unsigned long *)image->data;
+
+	/* if the richcursor is clipped, the fb patch will be smaller */
+	rsW = rcWidth;
+	rsX = 0;	/* used to denote a shift from the left side */
+	x = rcCursorX - rcHotX;
+	if (x < 0) {
+		rsW += x;
+		rsX = -x;
+	} else if (x + rsW > si.framebufferWidth) {
+		rsW = si.framebufferWidth - x;
+	}
+	rsH = rcHeight;
+	rsY = 0;	/* used to denote a shift from the top side */
+	y = rcCursorY - rcHotY;
+	if (y < 0) {
+		rsH += y;
+		rsY = -y;
+	} else if (y + rsH > si.framebufferHeight) {
+		rsH = si.framebufferHeight - y;
+	}
+
+	/*
+	 * now loop over the cursor data, blend in the fb values,
+	 * and then overwrite the fb (CopyDataToScreen())
+	 */
+	for (y = 0; y < rcHeight; y++) {
+		y0 = rcCursorY - rcHotY + y;
+		if (y0 < 0 || y0 >= si.framebufferHeight) {
+			continue;	/* clipped */
+		}
+		for (x = 0; x < rcWidth; x++) {
+			int alpha, color_curs, color_fb, i;
+
+			x0 = rcCursorX - rcHotX + x;
+			if (x0 < 0 || x0 >= si.framebufferWidth) {
+				continue;	/* clipped */
+			}
+
+			offset = y * rcWidth + x;
+			pos = (char *)&rcSource[offset * bytesPerPixel];
+
+			/* extract secret alpha byte from rich cursor: */
+			upos = (unsigned long *) pos;
+			alpha = (*upos & 0xff000000) >> 24;	/* XXX MSB? */
+
+			/* extract the pixel from the fb: */
+			pixel = *(upix + (y-rsY)*iwidth + (x-rsX));
+
+			put = 0;
+			/* for simplicity, blend all 4 bytes */
+			for (i = 0; i < 4; i++) {
+				int sh = i*8;
+				color_curs = ((0xff << sh) & *upos) >> sh;
+				color_fb   = ((0xff << sh) & pixel) >> sh;
+
+				/* XXX assumes pre-multipled color_curs */
+				color_fb = color_curs
+				    + ((0xff - alpha) * color_fb)/0xff;
+				put |= color_fb << sh;
+			}
+			/* place in the fb: */
+	    		CopyDataToScreen((char *)&put, x0, y0, 1, 1);
+		}
+	}
+	return;
+  }
+oldway:
+#endif
+
   bytesPerPixel = myFormat.bitsPerPixel / 8;
 
   /* FIXME: Speed optimization is possible. */