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 #include <rfb/rfb.h>
00026 #include <rfb/rfbregion.h>
00027 #include "private.h"
00028
00029 void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2);
00030
00031
00032
00033
00034
00035 rfbBool
00036 rfbSendCursorShape(rfbClientPtr cl)
00037 {
00038 rfbCursorPtr pCursor;
00039 rfbFramebufferUpdateRectHeader rect;
00040 rfbXCursorColors colors;
00041 int saved_ublen;
00042 int bitmapRowBytes, maskBytes, dataBytes;
00043 int i, j;
00044 uint8_t *bitmapData;
00045 uint8_t bitmapByte;
00046
00047
00048
00049 pCursor = cl->screen->getCursorPtr(cl);
00050
00051
00052 if (cl->useRichCursorEncoding) {
00053 if(pCursor && !pCursor->richSource)
00054 rfbMakeRichCursorFromXCursor(cl->screen,pCursor);
00055 rect.encoding = Swap32IfLE(rfbEncodingRichCursor);
00056 } else {
00057 if(pCursor && !pCursor->source)
00058 rfbMakeXCursorFromRichCursor(cl->screen,pCursor);
00059 rect.encoding = Swap32IfLE(rfbEncodingXCursor);
00060 }
00061
00062
00063
00064 if ( pCursor && pCursor->width == 1 &&
00065 pCursor->height == 1 &&
00066 pCursor->mask[0] == 0 ) {
00067 pCursor = NULL;
00068 }
00069
00070 if (pCursor == NULL) {
00071 if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) {
00072 if (!rfbSendUpdateBuf(cl))
00073 return FALSE;
00074 }
00075 rect.r.x = rect.r.y = 0;
00076 rect.r.w = rect.r.h = 0;
00077 memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
00078 sz_rfbFramebufferUpdateRectHeader);
00079 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
00080
00081 if (!rfbSendUpdateBuf(cl))
00082 return FALSE;
00083
00084 return TRUE;
00085 }
00086
00087
00088
00089 bitmapRowBytes = (pCursor->width + 7) / 8;
00090 maskBytes = bitmapRowBytes * pCursor->height;
00091 dataBytes = (cl->useRichCursorEncoding) ?
00092 (pCursor->width * pCursor->height *
00093 (cl->format.bitsPerPixel / 8)) : maskBytes;
00094
00095
00096
00097 if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
00098 sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
00099 if (!rfbSendUpdateBuf(cl))
00100 return FALSE;
00101 }
00102
00103 if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
00104 sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
00105 return FALSE;
00106 }
00107
00108 saved_ublen = cl->ublen;
00109
00110
00111
00112 rect.r.x = Swap16IfLE(pCursor->xhot);
00113 rect.r.y = Swap16IfLE(pCursor->yhot);
00114 rect.r.w = Swap16IfLE(pCursor->width);
00115 rect.r.h = Swap16IfLE(pCursor->height);
00116
00117 memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
00118 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
00119
00120
00121
00122 if (!cl->useRichCursorEncoding) {
00123
00124 colors.foreRed = (char)(pCursor->foreRed >> 8);
00125 colors.foreGreen = (char)(pCursor->foreGreen >> 8);
00126 colors.foreBlue = (char)(pCursor->foreBlue >> 8);
00127 colors.backRed = (char)(pCursor->backRed >> 8);
00128 colors.backGreen = (char)(pCursor->backGreen >> 8);
00129 colors.backBlue = (char)(pCursor->backBlue >> 8);
00130
00131 memcpy(&cl->updateBuf[cl->ublen], (char *)&colors, sz_rfbXCursorColors);
00132 cl->ublen += sz_rfbXCursorColors;
00133
00134 bitmapData = (uint8_t *)pCursor->source;
00135
00136 for (i = 0; i < pCursor->height; i++) {
00137 for (j = 0; j < bitmapRowBytes; j++) {
00138 bitmapByte = bitmapData[i * bitmapRowBytes + j];
00139 cl->updateBuf[cl->ublen++] = (char)bitmapByte;
00140 }
00141 }
00142 } else {
00143
00144 int bpp1=cl->screen->serverFormat.bitsPerPixel/8,
00145 bpp2=cl->format.bitsPerPixel/8;
00146 (*cl->translateFn)(cl->translateLookupTable,
00147 &(cl->screen->serverFormat),
00148 &cl->format, (char*)pCursor->richSource,
00149 &cl->updateBuf[cl->ublen],
00150 pCursor->width*bpp1, pCursor->width, pCursor->height);
00151
00152 cl->ublen += pCursor->width*bpp2*pCursor->height;
00153 }
00154
00155
00156
00157 bitmapData = (uint8_t *)pCursor->mask;
00158
00159 for (i = 0; i < pCursor->height; i++) {
00160 for (j = 0; j < bitmapRowBytes; j++) {
00161 bitmapByte = bitmapData[i * bitmapRowBytes + j];
00162 cl->updateBuf[cl->ublen++] = (char)bitmapByte;
00163 }
00164 }
00165
00166
00167 rfbStatRecordEncodingSent(cl, (cl->useRichCursorEncoding ? rfbEncodingRichCursor : rfbEncodingXCursor),
00168 sz_rfbFramebufferUpdateRectHeader + (cl->ublen - saved_ublen), sz_rfbFramebufferUpdateRectHeader + (cl->ublen - saved_ublen));
00169
00170 if (!rfbSendUpdateBuf(cl))
00171 return FALSE;
00172
00173 return TRUE;
00174 }
00175
00176
00177
00178
00179
00180 rfbBool
00181 rfbSendCursorPos(rfbClientPtr cl)
00182 {
00183 rfbFramebufferUpdateRectHeader rect;
00184
00185 if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
00186 if (!rfbSendUpdateBuf(cl))
00187 return FALSE;
00188 }
00189
00190 rect.encoding = Swap32IfLE(rfbEncodingPointerPos);
00191 rect.r.x = Swap16IfLE(cl->screen->cursorX);
00192 rect.r.y = Swap16IfLE(cl->screen->cursorY);
00193 rect.r.w = 0;
00194 rect.r.h = 0;
00195
00196 memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
00197 sz_rfbFramebufferUpdateRectHeader);
00198 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
00199
00200 rfbStatRecordEncodingSent(cl, rfbEncodingPointerPos, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader);
00201
00202 if (!rfbSendUpdateBuf(cl))
00203 return FALSE;
00204
00205 return TRUE;
00206 }
00207
00208
00209 unsigned char rfbReverseByte[0x100] = {
00210
00211 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
00212 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
00213 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
00214 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
00215 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
00216 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
00217 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
00218 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
00219 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
00220 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
00221 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
00222 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
00223 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
00224 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
00225 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
00226 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
00227 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
00228 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
00229 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
00230 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
00231 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
00232 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
00233 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
00234 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
00235 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
00236 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
00237 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
00238 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
00239 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
00240 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
00241 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
00242 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
00243 };
00244
00245 void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap)
00246 {
00247 int i,t=(width+7)/8*height;
00248 for(i=0;i<t;i++)
00249 bitmap[i]=rfbReverseByte[(int)bitmap[i]];
00250 }
00251
00252
00253
00254 rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskString)
00255 {
00256 int i,j,w=(width+7)/8;
00257 rfbCursorPtr cursor = (rfbCursorPtr)calloc(1,sizeof(rfbCursor));
00258 char* cp;
00259 unsigned char bit;
00260
00261 cursor->cleanup=TRUE;
00262 cursor->width=width;
00263 cursor->height=height;
00264
00265 cursor->foreRed=cursor->foreGreen=cursor->foreBlue=0xffff;
00266
00267 cursor->source = (unsigned char*)calloc(w,height);
00268 cursor->cleanupSource = TRUE;
00269 for(j=0,cp=cursorString;j<height;j++)
00270 for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
00271 if(*cp!=' ') cursor->source[j*w+i/8]|=bit;
00272
00273 if(maskString) {
00274 cursor->mask = (unsigned char*)calloc(w,height);
00275 for(j=0,cp=maskString;j<height;j++)
00276 for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
00277 if(*cp!=' ') cursor->mask[j*w+i/8]|=bit;
00278 } else
00279 cursor->mask = (unsigned char*)rfbMakeMaskForXCursor(width,height,(char*)cursor->source);
00280 cursor->cleanupMask = TRUE;
00281
00282 return(cursor);
00283 }
00284
00285 char* rfbMakeMaskForXCursor(int width,int height,char* source)
00286 {
00287 int i,j,w=(width+7)/8;
00288 char* mask=(char*)calloc(w,height);
00289 unsigned char c;
00290
00291 for(j=0;j<height;j++)
00292 for(i=w-1;i>=0;i--) {
00293 c=source[j*w+i];
00294 if(j>0) c|=source[(j-1)*w+i];
00295 if(j<height-1) c|=source[(j+1)*w+i];
00296
00297 if(i>0 && (c&0x80))
00298 mask[j*w+i-1]|=0x01;
00299 if(i<w-1 && (c&0x01))
00300 mask[j*w+i+1]|=0x80;
00301
00302 mask[j*w+i]|=(c<<1)|c|(c>>1);
00303 }
00304
00305 return(mask);
00306 }
00307
00308
00309
00310 char* rfbMakeMaskFromAlphaSource(int width,int height,unsigned char* alphaSource)
00311 {
00312 int* error=(int*)calloc(sizeof(int),width);
00313 int i,j,currentError=0,maskStride=(width+7)/8;
00314 unsigned char* result=(unsigned char*)calloc(maskStride,height);
00315
00316 for(j=0;j<height;j++)
00317 for(i=0;i<width;i++) {
00318 int right,middle,left;
00319 currentError+=alphaSource[i+width*j]+error[i];
00320
00321 if(currentError<0x80) {
00322
00323
00324 } else {
00325
00326 result[i/8+j*maskStride]|=(0x100>>(i&7));
00327
00328 currentError-=0xff;
00329 }
00330
00331 right=currentError/16;
00332 middle=currentError*5/16;
00333 left=currentError*3/16;
00334 currentError-=right+middle+left;
00335 error[i]=right;
00336 if(i>0) {
00337 error[i-1]=middle;
00338 if(i>1)
00339 error[i-2]=left;
00340 }
00341 }
00342 free(error);
00343 return (char *) result;
00344 }
00345
00346 void rfbFreeCursor(rfbCursorPtr cursor)
00347 {
00348 if(cursor) {
00349 if(cursor->cleanupRichSource && cursor->richSource)
00350 free(cursor->richSource);
00351 if(cursor->cleanupRichSource && cursor->alphaSource)
00352 free(cursor->alphaSource);
00353 if(cursor->cleanupSource && cursor->source)
00354 free(cursor->source);
00355 if(cursor->cleanupMask && cursor->mask)
00356 free(cursor->mask);
00357 if(cursor->cleanup)
00358 free(cursor);
00359 else {
00360 cursor->cleanup=cursor->cleanupSource=cursor->cleanupMask
00361 =cursor->cleanupRichSource=FALSE;
00362 cursor->source=cursor->mask=cursor->richSource=NULL;
00363 cursor->alphaSource=NULL;
00364 }
00365 }
00366
00367 }
00368
00369
00370 void rfbMakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
00371 {
00372 rfbPixelFormat* format=&rfbScreen->serverFormat;
00373 int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8,
00374 width=cursor->width*bpp;
00375 uint32_t background;
00376 char *back=(char*)&background;
00377 unsigned char bit;
00378 int interp = 0, db = 0;
00379
00380 if(cursor->source && cursor->cleanupSource)
00381 free(cursor->source);
00382 cursor->source=(unsigned char*)calloc(w,cursor->height);
00383 cursor->cleanupSource=TRUE;
00384
00385 if(format->bigEndian) {
00386 back+=4-bpp;
00387 }
00388
00389
00390 if (!cursor->backRed && !cursor->backGreen && !cursor->backBlue &&
00391 !cursor->foreRed && !cursor->foreGreen && !cursor->foreBlue) {
00392 if (format->trueColour && (bpp == 1 || bpp == 2 || bpp == 4)) {
00393 interp = 1;
00394 cursor->foreRed = cursor->foreGreen = cursor->foreBlue = 0xffff;
00395 }
00396 }
00397
00398 background = ((format->redMax * cursor->backRed) / 0xffff) << format->redShift |
00399 ((format->greenMax * cursor->backGreen) / 0xffff) << format->greenShift |
00400 ((format->blueMax * cursor->backBlue) / 0xffff) << format->blueShift;
00401
00402 #define SETRGB(u) \
00403 r = (255 * (((format->redMax << format->redShift) & (*u)) >> format->redShift)) / format->redMax; \
00404 g = (255 * (((format->greenMax << format->greenShift) & (*u)) >> format->greenShift)) / format->greenMax; \
00405 b = (255 * (((format->blueMax << format->blueShift) & (*u)) >> format->blueShift)) / format->blueMax;
00406
00407 if (db) fprintf(stderr, "interp: %d\n", interp);
00408
00409 for(j=0;j<cursor->height;j++) {
00410 for(i=0,bit=0x80;i<cursor->width;i++,bit=(bit&1)?0x80:bit>>1) {
00411 if (interp) {
00412 int r = 0, g = 0, b = 0, grey;
00413 unsigned char *p = cursor->richSource+j*width+i*bpp;
00414 if (bpp == 1) {
00415 unsigned char* uc = (unsigned char*) p;
00416 SETRGB(uc);
00417 } else if (bpp == 2) {
00418 unsigned short* us = (unsigned short*) p;
00419 SETRGB(us);
00420 } else if (bpp == 4) {
00421 unsigned int* ui = (unsigned int*) p;
00422 SETRGB(ui);
00423 }
00424 grey = (r + g + b) / 3;
00425 if (grey >= 128) {
00426 cursor->source[j*w+i/8]|=bit;
00427 if (db) fprintf(stderr, "1");
00428 } else {
00429 if (db) fprintf(stderr, "0");
00430 }
00431
00432 } else if(memcmp(cursor->richSource+j*width+i*bpp, back, bpp)) {
00433 cursor->source[j*w+i/8]|=bit;
00434 }
00435 }
00436 if (db) fprintf(stderr, "\n");
00437 }
00438 }
00439
00440 void rfbMakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
00441 {
00442 rfbPixelFormat* format=&rfbScreen->serverFormat;
00443 int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8;
00444 uint32_t background,foreground;
00445 char *back=(char*)&background,*fore=(char*)&foreground;
00446 unsigned char *cp;
00447 unsigned char bit;
00448
00449 if(cursor->richSource && cursor->cleanupRichSource)
00450 free(cursor->richSource);
00451 cp=cursor->richSource=(unsigned char*)calloc(cursor->width*bpp,cursor->height);
00452 cursor->cleanupRichSource=TRUE;
00453
00454 if(format->bigEndian) {
00455 back+=4-bpp;
00456 fore+=4-bpp;
00457 }
00458
00459 background=cursor->backRed<<format->redShift|
00460 cursor->backGreen<<format->greenShift|cursor->backBlue<<format->blueShift;
00461 foreground=cursor->foreRed<<format->redShift|
00462 cursor->foreGreen<<format->greenShift|cursor->foreBlue<<format->blueShift;
00463
00464 for(j=0;j<cursor->height;j++)
00465 for(i=0,bit=0x80;i<cursor->width;i++,bit=(bit&1)?0x80:bit>>1,cp+=bpp)
00466 if(cursor->source[j*w+i/8]&bit) memcpy(cp,fore,bpp);
00467 else memcpy(cp,back,bpp);
00468 }
00469
00470
00471
00472 void rfbHideCursor(rfbClientPtr cl)
00473 {
00474 rfbScreenInfoPtr s=cl->screen;
00475 rfbCursorPtr c=s->cursor;
00476 int j,x1,x2,y1,y2,bpp=s->serverFormat.bitsPerPixel/8,
00477 rowstride=s->paddedWidthInBytes;
00478 LOCK(s->cursorMutex);
00479 if(!c) {
00480 UNLOCK(s->cursorMutex);
00481 return;
00482 }
00483
00484
00485 x1=cl->cursorX-c->xhot;
00486 x2=x1+c->width;
00487 if(x1<0) x1=0;
00488 if(x2>=s->width) x2=s->width-1;
00489 x2-=x1; if(x2<=0) {
00490 UNLOCK(s->cursorMutex);
00491 return;
00492 }
00493 y1=cl->cursorY-c->yhot;
00494 y2=y1+c->height;
00495 if(y1<0) y1=0;
00496 if(y2>=s->height) y2=s->height-1;
00497 y2-=y1; if(y2<=0) {
00498 UNLOCK(s->cursorMutex);
00499 return;
00500 }
00501
00502
00503 for(j=0;j<y2;j++)
00504 memcpy(s->frameBuffer+(y1+j)*rowstride+x1*bpp,
00505 s->underCursorBuffer+j*x2*bpp,
00506 x2*bpp);
00507
00508
00509 rfbScaledScreenUpdate(s, x1, y1, x1+x2, y1+y2);
00510
00511 UNLOCK(s->cursorMutex);
00512 }
00513
00514 void rfbShowCursor(rfbClientPtr cl)
00515 {
00516 rfbScreenInfoPtr s=cl->screen;
00517 rfbCursorPtr c=s->cursor;
00518 int i,j,x1,x2,y1,y2,i1,j1,bpp=s->serverFormat.bitsPerPixel/8,
00519 rowstride=s->paddedWidthInBytes,
00520 bufSize,w;
00521 rfbBool wasChanged=FALSE;
00522
00523 if(!c) return;
00524 LOCK(s->cursorMutex);
00525
00526 bufSize=c->width*c->height*bpp;
00527 w=(c->width+7)/8;
00528 if(s->underCursorBufferLen<bufSize) {
00529 if(s->underCursorBuffer!=NULL)
00530 free(s->underCursorBuffer);
00531 s->underCursorBuffer=malloc(bufSize);
00532 s->underCursorBufferLen=bufSize;
00533 }
00534
00535
00536 i1=j1=0;
00537 x1=cl->cursorX-c->xhot;
00538 x2=x1+c->width;
00539 if(x1<0) { i1=-x1; x1=0; }
00540 if(x2>=s->width) x2=s->width-1;
00541 x2-=x1; if(x2<=0) {
00542 UNLOCK(s->cursorMutex);
00543 return;
00544 }
00545
00546 y1=cl->cursorY-c->yhot;
00547 y2=y1+c->height;
00548 if(y1<0) { j1=-y1; y1=0; }
00549 if(y2>=s->height) y2=s->height-1;
00550 y2-=y1; if(y2<=0) {
00551 UNLOCK(s->cursorMutex);
00552 return;
00553 }
00554
00555
00556 for(j=0;j<y2;j++) {
00557 char* dest=s->underCursorBuffer+j*x2*bpp;
00558 const char* src=s->frameBuffer+(y1+j)*rowstride+x1*bpp;
00559 unsigned int count=x2*bpp;
00560 if(wasChanged || memcmp(dest,src,count)) {
00561 wasChanged=TRUE;
00562 memcpy(dest,src,count);
00563 }
00564 }
00565
00566 if(!c->richSource)
00567 rfbMakeRichCursorFromXCursor(s,c);
00568
00569 if (c->alphaSource) {
00570 int rmax, rshift;
00571 int gmax, gshift;
00572 int bmax, bshift;
00573 int amax = 255;
00574 unsigned int rmask, gmask, bmask;
00575
00576 rmax = s->serverFormat.redMax;
00577 gmax = s->serverFormat.greenMax;
00578 bmax = s->serverFormat.blueMax;
00579 rshift = s->serverFormat.redShift;
00580 gshift = s->serverFormat.greenShift;
00581 bshift = s->serverFormat.blueShift;
00582
00583 rmask = (rmax << rshift);
00584 gmask = (gmax << gshift);
00585 bmask = (bmax << bshift);
00586
00587 for(j=0;j<y2;j++) {
00588 for(i=0;i<x2;i++) {
00589
00590
00591
00592
00593 char *dest;
00594 unsigned char *src, *aptr;
00595 unsigned int val, dval, sval;
00596 int rdst, gdst, bdst;
00597 int asrc, rsrc, gsrc, bsrc;
00598
00599 dest = s->frameBuffer + (j+y1)*rowstride + (i+x1)*bpp;
00600 src = c->richSource + (j+j1)*c->width*bpp + (i+i1)*bpp;
00601 aptr = c->alphaSource + (j+j1)*c->width + (i+i1);
00602
00603 asrc = *aptr;
00604 if (!asrc) {
00605 continue;
00606 }
00607
00608 if (bpp == 1) {
00609 dval = *((unsigned char*) dest);
00610 sval = *((unsigned char*) src);
00611 } else if (bpp == 2) {
00612 dval = *((unsigned short*) dest);
00613 sval = *((unsigned short*) src);
00614 } else if (bpp == 3) {
00615 unsigned char *dst = (unsigned char *) dest;
00616 dval = 0;
00617 dval |= ((*(dst+0)) << 0);
00618 dval |= ((*(dst+1)) << 8);
00619 dval |= ((*(dst+2)) << 16);
00620 sval = 0;
00621 sval |= ((*(src+0)) << 0);
00622 sval |= ((*(src+1)) << 8);
00623 sval |= ((*(src+2)) << 16);
00624 } else if (bpp == 4) {
00625 dval = *((unsigned int*) dest);
00626 sval = *((unsigned int*) src);
00627 } else {
00628 continue;
00629 }
00630
00631
00632 rdst = (dval & rmask) >> rshift;
00633 gdst = (dval & gmask) >> gshift;
00634 bdst = (dval & bmask) >> bshift;
00635
00636 rsrc = (sval & rmask) >> rshift;
00637 gsrc = (sval & gmask) >> gshift;
00638 bsrc = (sval & bmask) >> bshift;
00639
00640
00641 if (! c->alphaPreMultiplied) {
00642 rsrc = (asrc * rsrc)/amax;
00643 gsrc = (asrc * gsrc)/amax;
00644 bsrc = (asrc * bsrc)/amax;
00645 }
00646 rdst = rsrc + ((amax - asrc) * rdst)/amax;
00647 gdst = gsrc + ((amax - asrc) * gdst)/amax;
00648 bdst = bsrc + ((amax - asrc) * bdst)/amax;
00649
00650 val = 0;
00651 val |= (rdst << rshift);
00652 val |= (gdst << gshift);
00653 val |= (bdst << bshift);
00654
00655
00656 memcpy(dest, &val, bpp);
00657 }
00658 }
00659 } else {
00660
00661 for(j=0;j<y2;j++)
00662 for(i=0;i<x2;i++)
00663 if((c->mask[(j+j1)*w+(i+i1)/8]<<((i+i1)&7))&0x80)
00664 memcpy(s->frameBuffer+(j+y1)*rowstride+(i+x1)*bpp,
00665 c->richSource+(j+j1)*c->width*bpp+(i+i1)*bpp,bpp);
00666 }
00667
00668
00669 rfbScaledScreenUpdate(s, x1, y1, x1+x2, y1+y2);
00670
00671 UNLOCK(s->cursorMutex);
00672 }
00673
00674
00675
00676
00677
00678
00679
00680 void rfbRedrawAfterHideCursor(rfbClientPtr cl,sraRegionPtr updateRegion)
00681 {
00682 rfbScreenInfoPtr s = cl->screen;
00683 rfbCursorPtr c = s->cursor;
00684
00685 if(c) {
00686 int x,y,x2,y2;
00687
00688 x = cl->cursorX-c->xhot;
00689 y = cl->cursorY-c->yhot;
00690 x2 = x+c->width;
00691 y2 = y+c->height;
00692
00693 if(sraClipRect2(&x,&y,&x2,&y2,0,0,s->width,s->height)) {
00694 sraRegionPtr rect;
00695 rect = sraRgnCreateRect(x,y,x2,y2);
00696 if(updateRegion) {
00697 sraRgnOr(updateRegion,rect);
00698 } else {
00699 LOCK(cl->updateMutex);
00700 sraRgnOr(cl->modifiedRegion,rect);
00701 UNLOCK(cl->updateMutex);
00702 }
00703 sraRgnDestroy(rect);
00704 }
00705 }
00706 }
00707
00708 #ifdef DEBUG
00709
00710 static void rfbPrintXCursor(rfbCursorPtr cursor)
00711 {
00712 int i,i1,j,w=(cursor->width+7)/8;
00713 unsigned char bit;
00714 for(j=0;j<cursor->height;j++) {
00715 for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
00716 if(cursor->source[j*w+i]&bit) putchar('#'); else putchar(' ');
00717 putchar(':');
00718 for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
00719 if(cursor->mask[j*w+i]&bit) putchar('#'); else putchar(' ');
00720 putchar('\n');
00721 }
00722 }
00723
00724 #endif
00725
00726 void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c)
00727 {
00728 rfbClientIteratorPtr iterator;
00729 rfbClientPtr cl;
00730
00731 LOCK(rfbScreen->cursorMutex);
00732
00733 if(rfbScreen->cursor) {
00734 iterator=rfbGetClientIterator(rfbScreen);
00735 while((cl=rfbClientIteratorNext(iterator)))
00736 if(!cl->enableCursorShapeUpdates)
00737 rfbRedrawAfterHideCursor(cl,NULL);
00738 rfbReleaseClientIterator(iterator);
00739
00740 if(rfbScreen->cursor->cleanup)
00741 rfbFreeCursor(rfbScreen->cursor);
00742 }
00743
00744 rfbScreen->cursor = c;
00745
00746 iterator=rfbGetClientIterator(rfbScreen);
00747 while((cl=rfbClientIteratorNext(iterator))) {
00748 cl->cursorWasChanged = TRUE;
00749 if(!cl->enableCursorShapeUpdates)
00750 rfbRedrawAfterHideCursor(cl,NULL);
00751 }
00752 rfbReleaseClientIterator(iterator);
00753
00754 UNLOCK(rfbScreen->cursorMutex);
00755 }
00756