summaryrefslogtreecommitdiffstats
path: root/krfb/libvncserver/hextile.c
diff options
context:
space:
mode:
Diffstat (limited to 'krfb/libvncserver/hextile.c')
-rw-r--r--krfb/libvncserver/hextile.c347
1 files changed, 347 insertions, 0 deletions
diff --git a/krfb/libvncserver/hextile.c b/krfb/libvncserver/hextile.c
new file mode 100644
index 00000000..6166844e
--- /dev/null
+++ b/krfb/libvncserver/hextile.c
@@ -0,0 +1,347 @@
+/*
+ * hextile.c
+ *
+ * Routines to implement Hextile Encoding
+ */
+
+/*
+ * OSXvnc Copyright (C) 2001 Dan McGuirk <[email protected]>.
+ * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
+ * All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+#include "rfb.h"
+
+static Bool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h);
+static Bool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h);
+static Bool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h);
+
+
+/*
+ * rfbSendRectEncodingHextile - send a rectangle using hextile encoding.
+ */
+
+Bool
+rfbSendRectEncodingHextile(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ rfbFramebufferUpdateRectHeader rect;
+
+ if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.r.x = Swap16IfLE(x);
+ rect.r.y = Swap16IfLE(y);
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+ rect.encoding = Swap32IfLE(rfbEncodingHextile);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cl->rfbRectanglesSent[rfbEncodingHextile]++;
+ cl->rfbBytesSent[rfbEncodingHextile] += sz_rfbFramebufferUpdateRectHeader;
+
+ switch (cl->format.bitsPerPixel) {
+ case 8:
+ return sendHextiles8(cl, x, y, w, h);
+ case 16:
+ return sendHextiles16(cl, x, y, w, h);
+ case 32:
+ return sendHextiles32(cl, x, y, w, h);
+ }
+
+ rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel);
+ return FALSE;
+}
+
+
+#define PUT_PIXEL8(pix) (cl->updateBuf[cl->ublen++] = (pix))
+
+#define PUT_PIXEL16(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
+ cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1])
+
+#define PUT_PIXEL32(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
+ cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1], \
+ cl->updateBuf[cl->ublen++] = ((char*)&(pix))[2], \
+ cl->updateBuf[cl->ublen++] = ((char*)&(pix))[3])
+
+
+#define DEFINE_SEND_HEXTILES(bpp) \
+ \
+ \
+static Bool subrectEncode##bpp(rfbClientPtr cli, CARD##bpp *data, int w, int h, \
+ CARD##bpp bg, CARD##bpp fg, Bool mono); \
+static void testColours##bpp(CARD##bpp *data, int size, Bool *mono, \
+ Bool *solid, CARD##bpp *bg, CARD##bpp *fg); \
+ \
+ \
+/* \
+ * rfbSendHextiles \
+ */ \
+ \
+static Bool \
+sendHextiles##bpp(cl, rx, ry, rw, rh) \
+ rfbClientPtr cl; \
+ int rx, ry, rw, rh; \
+{ \
+ int x, y, w, h; \
+ int startUblen; \
+ char *fbptr; \
+ CARD##bpp bg = 0, fg = 0, newBg, newFg; \
+ Bool mono, solid; \
+ Bool validBg = FALSE; \
+ Bool validFg = FALSE; \
+ CARD##bpp clientPixelData[16*16*(bpp/8)]; \
+ \
+ for (y = ry; y < ry+rh; y += 16) { \
+ for (x = rx; x < rx+rw; x += 16) { \
+ w = h = 16; \
+ if (rx+rw - x < 16) \
+ w = rx+rw - x; \
+ if (ry+rh - y < 16) \
+ h = ry+rh - y; \
+ \
+ if ((cl->ublen + 1 + (2 + 16 * 16) * (bpp/8)) > \
+ UPDATE_BUF_SIZE) { \
+ if (!rfbSendUpdateBuf(cl)) \
+ return FALSE; \
+ } \
+ \
+ fbptr = (cl->screen->frameBuffer + (cl->screen->paddedWidthInBytes * y) \
+ + (x * (cl->screen->bitsPerPixel / 8))); \
+ \
+ (*cl->translateFn)(cl->translateLookupTable, &(cl->screen->rfbServerFormat), \
+ &cl->format, fbptr, (char *)clientPixelData, \
+ cl->screen->paddedWidthInBytes, w, h); \
+ \
+ startUblen = cl->ublen; \
+ cl->updateBuf[startUblen] = 0; \
+ cl->ublen++; \
+ \
+ testColours##bpp(clientPixelData, w * h, \
+ &mono, &solid, &newBg, &newFg); \
+ \
+ if (!validBg || (newBg != bg)) { \
+ validBg = TRUE; \
+ bg = newBg; \
+ cl->updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \
+ PUT_PIXEL##bpp(bg); \
+ } \
+ \
+ if (solid) { \
+ cl->rfbBytesSent[rfbEncodingHextile] += cl->ublen - startUblen; \
+ continue; \
+ } \
+ \
+ cl->updateBuf[startUblen] |= rfbHextileAnySubrects; \
+ \
+ if (mono) { \
+ if (!validFg || (newFg != fg)) { \
+ validFg = TRUE; \
+ fg = newFg; \
+ cl->updateBuf[startUblen] |= rfbHextileForegroundSpecified; \
+ PUT_PIXEL##bpp(fg); \
+ } \
+ } else { \
+ validFg = FALSE; \
+ cl->updateBuf[startUblen] |= rfbHextileSubrectsColoured; \
+ } \
+ \
+ if (!subrectEncode##bpp(cl, clientPixelData, w, h, bg, fg, mono)) { \
+ /* encoding was too large, use raw */ \
+ validBg = FALSE; \
+ validFg = FALSE; \
+ cl->ublen = startUblen; \
+ cl->updateBuf[cl->ublen++] = rfbHextileRaw; \
+ (*cl->translateFn)(cl->translateLookupTable, \
+ &(cl->screen->rfbServerFormat), &cl->format, fbptr, \
+ (char *)clientPixelData, \
+ cl->screen->paddedWidthInBytes, w, h); \
+ \
+ memcpy(&cl->updateBuf[cl->ublen], (char *)clientPixelData, \
+ w * h * (bpp/8)); \
+ \
+ cl->ublen += w * h * (bpp/8); \
+ } \
+ \
+ cl->rfbBytesSent[rfbEncodingHextile] += cl->ublen - startUblen; \
+ } \
+ } \
+ \
+ return TRUE; \
+} \
+ \
+ \
+static Bool \
+subrectEncode##bpp(rfbClientPtr cl, CARD##bpp *data, int w, int h, \
+ CARD##bpp bg, CARD##bpp fg, Bool mono) \
+{ \
+ CARD##bpp cl2; \
+ int x,y; \
+ int i,j; \
+ int hx=0,hy,vx=0,vy; \
+ int hyflag; \
+ CARD##bpp *seg; \
+ CARD##bpp *line; \
+ int hw,hh,vw,vh; \
+ int thex,they,thew,theh; \
+ int numsubs = 0; \
+ int newLen; \
+ int nSubrectsUblen; \
+ \
+ nSubrectsUblen = cl->ublen; \
+ cl->ublen++; \
+ \
+ for (y=0; y<h; y++) { \
+ line = data+(y*w); \
+ for (x=0; x<w; x++) { \
+ if (line[x] != bg) { \
+ cl2 = line[x]; \
+ hy = y-1; \
+ hyflag = 1; \
+ for (j=y; j<h; j++) { \
+ seg = data+(j*w); \
+ if (seg[x] != cl2) {break;} \
+ i = x; \
+ while ((seg[i] == cl2) && (i < w)) i += 1; \
+ i -= 1; \
+ if (j == y) vx = hx = i; \
+ if (i < vx) vx = i; \
+ if ((hyflag > 0) && (i >= hx)) { \
+ hy += 1; \
+ } else { \
+ hyflag = 0; \
+ } \
+ } \
+ vy = j-1; \
+ \
+ /* We now have two possible subrects: (x,y,hx,hy) and \
+ * (x,y,vx,vy). We'll choose the bigger of the two. \
+ */ \
+ hw = hx-x+1; \
+ hh = hy-y+1; \
+ vw = vx-x+1; \
+ vh = vy-y+1; \
+ \
+ thex = x; \
+ they = y; \
+ \
+ if ((hw*hh) > (vw*vh)) { \
+ thew = hw; \
+ theh = hh; \
+ } else { \
+ thew = vw; \
+ theh = vh; \
+ } \
+ \
+ if (mono) { \
+ newLen = cl->ublen - nSubrectsUblen + 2; \
+ } else { \
+ newLen = cl->ublen - nSubrectsUblen + bpp/8 + 2; \
+ } \
+ \
+ if (newLen > (w * h * (bpp/8))) \
+ return FALSE; \
+ \
+ numsubs += 1; \
+ \
+ if (!mono) PUT_PIXEL##bpp(cl2); \
+ \
+ cl->updateBuf[cl->ublen++] = rfbHextilePackXY(thex,they); \
+ cl->updateBuf[cl->ublen++] = rfbHextilePackWH(thew,theh); \
+ \
+ /* \
+ * Now mark the subrect as done. \
+ */ \
+ for (j=they; j < (they+theh); j++) { \
+ for (i=thex; i < (thex+thew); i++) { \
+ data[j*w+i] = bg; \
+ } \
+ } \
+ } \
+ } \
+ } \
+ \
+ cl->updateBuf[nSubrectsUblen] = numsubs; \
+ \
+ return TRUE; \
+} \
+ \
+ \
+/* \
+ * testColours() tests if there are one (solid), two (mono) or more \
+ * colours in a tile and gets a reasonable guess at the best background \
+ * pixel, and the foreground pixel for mono. \
+ */ \
+ \
+static void \
+testColours##bpp(data,size,mono,solid,bg,fg) \
+ CARD##bpp *data; \
+ int size; \
+ Bool *mono; \
+ Bool *solid; \
+ CARD##bpp *bg; \
+ CARD##bpp *fg; \
+{ \
+ CARD##bpp colour1 = 0, colour2 = 0; \
+ int n1 = 0, n2 = 0; \
+ *mono = TRUE; \
+ *solid = TRUE; \
+ \
+ for (; size > 0; size--, data++) { \
+ \
+ if (n1 == 0) \
+ colour1 = *data; \
+ \
+ if (*data == colour1) { \
+ n1++; \
+ continue; \
+ } \
+ \
+ if (n2 == 0) { \
+ *solid = FALSE; \
+ colour2 = *data; \
+ } \
+ \
+ if (*data == colour2) { \
+ n2++; \
+ continue; \
+ } \
+ \
+ *mono = FALSE; \
+ break; \
+ } \
+ \
+ if (n1 > n2) { \
+ *bg = colour1; \
+ *fg = colour2; \
+ } else { \
+ *bg = colour2; \
+ *fg = colour1; \
+ } \
+}
+
+DEFINE_SEND_HEXTILES(8)
+DEFINE_SEND_HEXTILES(16)
+DEFINE_SEND_HEXTILES(32)