00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <rfb/rfb.h>
00029
00030 static rfbBool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h);
00031 static rfbBool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h);
00032 static rfbBool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h);
00033
00034
00035
00036
00037
00038
00039 rfbBool
00040 rfbSendRectEncodingHextile(rfbClientPtr cl,
00041 int x,
00042 int y,
00043 int w,
00044 int h)
00045 {
00046 rfbFramebufferUpdateRectHeader rect;
00047
00048 if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
00049 if (!rfbSendUpdateBuf(cl))
00050 return FALSE;
00051 }
00052
00053 rect.r.x = Swap16IfLE(x);
00054 rect.r.y = Swap16IfLE(y);
00055 rect.r.w = Swap16IfLE(w);
00056 rect.r.h = Swap16IfLE(h);
00057 rect.encoding = Swap32IfLE(rfbEncodingHextile);
00058
00059 memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
00060 sz_rfbFramebufferUpdateRectHeader);
00061 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
00062
00063 rfbStatRecordEncodingSent(cl, rfbEncodingHextile,
00064 sz_rfbFramebufferUpdateRectHeader,
00065 sz_rfbFramebufferUpdateRectHeader + w * (cl->format.bitsPerPixel / 8) * h);
00066
00067 switch (cl->format.bitsPerPixel) {
00068 case 8:
00069 return sendHextiles8(cl, x, y, w, h);
00070 case 16:
00071 return sendHextiles16(cl, x, y, w, h);
00072 case 32:
00073 return sendHextiles32(cl, x, y, w, h);
00074 }
00075
00076 rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel);
00077 return FALSE;
00078 }
00079
00080
00081 #define PUT_PIXEL8(pix) (cl->updateBuf[cl->ublen++] = (pix))
00082
00083 #define PUT_PIXEL16(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
00084 cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1])
00085
00086 #define PUT_PIXEL32(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
00087 cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1], \
00088 cl->updateBuf[cl->ublen++] = ((char*)&(pix))[2], \
00089 cl->updateBuf[cl->ublen++] = ((char*)&(pix))[3])
00090
00091
00092 #define DEFINE_SEND_HEXTILES(bpp) \
00093 \
00094 \
00095 static rfbBool subrectEncode##bpp(rfbClientPtr cli, uint##bpp##_t *data, \
00096 int w, int h, uint##bpp##_t bg, uint##bpp##_t fg, rfbBool mono);\
00097 static void testColours##bpp(uint##bpp##_t *data, int size, rfbBool *mono, \
00098 rfbBool *solid, uint##bpp##_t *bg, uint##bpp##_t *fg); \
00099 \
00100 \
00101
00102
00103 \
00104 \
00105 static rfbBool \
00106 sendHextiles##bpp(rfbClientPtr cl, int rx, int ry, int rw, int rh) { \
00107 int x, y, w, h; \
00108 int startUblen; \
00109 char *fbptr; \
00110 uint##bpp##_t bg = 0, fg = 0, newBg, newFg; \
00111 rfbBool mono, solid; \
00112 rfbBool validBg = FALSE; \
00113 rfbBool validFg = FALSE; \
00114 uint##bpp##_t clientPixelData[16*16*(bpp/8)]; \
00115 \
00116 for (y = ry; y < ry+rh; y += 16) { \
00117 for (x = rx; x < rx+rw; x += 16) { \
00118 w = h = 16; \
00119 if (rx+rw - x < 16) \
00120 w = rx+rw - x; \
00121 if (ry+rh - y < 16) \
00122 h = ry+rh - y; \
00123 \
00124 if ((cl->ublen + 1 + (2 + 16 * 16) * (bpp/8)) > \
00125 UPDATE_BUF_SIZE) { \
00126 if (!rfbSendUpdateBuf(cl)) \
00127 return FALSE; \
00128 } \
00129 \
00130 fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) \
00131 + (x * (cl->scaledScreen->bitsPerPixel / 8))); \
00132 \
00133 (*cl->translateFn)(cl->translateLookupTable, &(cl->screen->serverFormat), \
00134 &cl->format, fbptr, (char *)clientPixelData, \
00135 cl->scaledScreen->paddedWidthInBytes, w, h); \
00136 \
00137 startUblen = cl->ublen; \
00138 cl->updateBuf[startUblen] = 0; \
00139 cl->ublen++; \
00140 rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
00141 \
00142 testColours##bpp(clientPixelData, w * h, \
00143 &mono, &solid, &newBg, &newFg); \
00144 \
00145 if (!validBg || (newBg != bg)) { \
00146 validBg = TRUE; \
00147 bg = newBg; \
00148 cl->updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \
00149 PUT_PIXEL##bpp(bg); \
00150 } \
00151 \
00152 if (solid) { \
00153 continue; \
00154 } \
00155 \
00156 cl->updateBuf[startUblen] |= rfbHextileAnySubrects; \
00157 \
00158 if (mono) { \
00159 if (!validFg || (newFg != fg)) { \
00160 validFg = TRUE; \
00161 fg = newFg; \
00162 cl->updateBuf[startUblen] |= rfbHextileForegroundSpecified; \
00163 PUT_PIXEL##bpp(fg); \
00164 } \
00165 } else { \
00166 validFg = FALSE; \
00167 cl->updateBuf[startUblen] |= rfbHextileSubrectsColoured; \
00168 } \
00169 \
00170 if (!subrectEncode##bpp(cl, clientPixelData, w, h, bg, fg, mono)) { \
00171 \
00172 validBg = FALSE; \
00173 validFg = FALSE; \
00174 cl->ublen = startUblen; \
00175 cl->updateBuf[cl->ublen++] = rfbHextileRaw; \
00176 (*cl->translateFn)(cl->translateLookupTable, \
00177 &(cl->screen->serverFormat), &cl->format, fbptr, \
00178 (char *)clientPixelData, \
00179 cl->scaledScreen->paddedWidthInBytes, w, h); \
00180 \
00181 memcpy(&cl->updateBuf[cl->ublen], (char *)clientPixelData, \
00182 w * h * (bpp/8)); \
00183 \
00184 cl->ublen += w * h * (bpp/8); \
00185 rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, \
00186 w * h * (bpp/8)); \
00187 } \
00188 } \
00189 } \
00190 \
00191 return TRUE; \
00192 } \
00193 \
00194 \
00195 static rfbBool \
00196 subrectEncode##bpp(rfbClientPtr cl, uint##bpp##_t *data, int w, int h, \
00197 uint##bpp##_t bg, uint##bpp##_t fg, rfbBool mono) \
00198 { \
00199 uint##bpp##_t cl2; \
00200 int x,y; \
00201 int i,j; \
00202 int hx=0,hy,vx=0,vy; \
00203 int hyflag; \
00204 uint##bpp##_t *seg; \
00205 uint##bpp##_t *line; \
00206 int hw,hh,vw,vh; \
00207 int thex,they,thew,theh; \
00208 int numsubs = 0; \
00209 int newLen; \
00210 int nSubrectsUblen; \
00211 \
00212 nSubrectsUblen = cl->ublen; \
00213 cl->ublen++; \
00214 rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
00215 \
00216 for (y=0; y<h; y++) { \
00217 line = data+(y*w); \
00218 for (x=0; x<w; x++) { \
00219 if (line[x] != bg) { \
00220 cl2 = line[x]; \
00221 hy = y-1; \
00222 hyflag = 1; \
00223 for (j=y; j<h; j++) { \
00224 seg = data+(j*w); \
00225 if (seg[x] != cl2) {break;} \
00226 i = x; \
00227 while ((seg[i] == cl2) && (i < w)) i += 1; \
00228 i -= 1; \
00229 if (j == y) vx = hx = i; \
00230 if (i < vx) vx = i; \
00231 if ((hyflag > 0) && (i >= hx)) { \
00232 hy += 1; \
00233 } else { \
00234 hyflag = 0; \
00235 } \
00236 } \
00237 vy = j-1; \
00238 \
00239
00240
00241 \
00242 hw = hx-x+1; \
00243 hh = hy-y+1; \
00244 vw = vx-x+1; \
00245 vh = vy-y+1; \
00246 \
00247 thex = x; \
00248 they = y; \
00249 \
00250 if ((hw*hh) > (vw*vh)) { \
00251 thew = hw; \
00252 theh = hh; \
00253 } else { \
00254 thew = vw; \
00255 theh = vh; \
00256 } \
00257 \
00258 if (mono) { \
00259 newLen = cl->ublen - nSubrectsUblen + 2; \
00260 } else { \
00261 newLen = cl->ublen - nSubrectsUblen + bpp/8 + 2; \
00262 } \
00263 \
00264 if (newLen > (w * h * (bpp/8))) \
00265 return FALSE; \
00266 \
00267 numsubs += 1; \
00268 \
00269 if (!mono) PUT_PIXEL##bpp(cl2); \
00270 \
00271 cl->updateBuf[cl->ublen++] = rfbHextilePackXY(thex,they); \
00272 cl->updateBuf[cl->ublen++] = rfbHextilePackWH(thew,theh); \
00273 rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
00274 \
00275
00276
00277 \
00278 for (j=they; j < (they+theh); j++) { \
00279 for (i=thex; i < (thex+thew); i++) { \
00280 data[j*w+i] = bg; \
00281 } \
00282 } \
00283 } \
00284 } \
00285 } \
00286 \
00287 cl->updateBuf[nSubrectsUblen] = numsubs; \
00288 \
00289 return TRUE; \
00290 } \
00291 \
00292 \
00293
00294
00295
00296
00297 \
00298 \
00299 static void \
00300 testColours##bpp(uint##bpp##_t *data, int size, rfbBool *mono, rfbBool *solid, \
00301 uint##bpp##_t *bg, uint##bpp##_t *fg) { \
00302 uint##bpp##_t colour1 = 0, colour2 = 0; \
00303 int n1 = 0, n2 = 0; \
00304 *mono = TRUE; \
00305 *solid = TRUE; \
00306 \
00307 for (; size > 0; size--, data++) { \
00308 \
00309 if (n1 == 0) \
00310 colour1 = *data; \
00311 \
00312 if (*data == colour1) { \
00313 n1++; \
00314 continue; \
00315 } \
00316 \
00317 if (n2 == 0) { \
00318 *solid = FALSE; \
00319 colour2 = *data; \
00320 } \
00321 \
00322 if (*data == colour2) { \
00323 n2++; \
00324 continue; \
00325 } \
00326 \
00327 *mono = FALSE; \
00328 break; \
00329 } \
00330 \
00331 if (n1 > n2) { \
00332 *bg = colour1; \
00333 *fg = colour2; \
00334 } else { \
00335 *bg = colour2; \
00336 *fg = colour1; \
00337 } \
00338 }
00339
00340 DEFINE_SEND_HEXTILES(8)
00341 DEFINE_SEND_HEXTILES(16)
00342 DEFINE_SEND_HEXTILES(32)