|
Line 0
Link Here
|
|
|
1 |
/* |
| 2 |
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. |
| 3 |
* Copyright (C) 2002 Tim Jansen. All Rights Reserved. |
| 4 |
* Copyright (C) 1999-2001 Anders Lindstr�m |
| 5 |
* |
| 6 |
* |
| 7 |
* |
| 8 |
* This is free software; you can redistribute it and/or modify |
| 9 |
* it under the terms of the GNU General Public License as published by |
| 10 |
* the Free Software Foundation; either version 2 of the License, or |
| 11 |
* (at your option) any later version. |
| 12 |
* |
| 13 |
* This software is distributed in the hope that it will be useful, |
| 14 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 |
* GNU General Public License for more details. |
| 17 |
* |
| 18 |
* You should have received a copy of the GNU General Public License |
| 19 |
* along with this software; if not, write to the Free Software |
| 20 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, |
| 21 |
* USA. |
| 22 |
* |
| 23 |
* tim@tjansen.de: - removed stuff for krdc |
| 24 |
* - merged with shm.c and misc.c |
| 25 |
* - added FillRectangle and Sync methods to draw only on |
| 26 |
* the image |
| 27 |
* - added Zoom functionality, based on rotation funcs from |
| 28 |
* SGE by Anders Lindstr�m) |
| 29 |
* - added support for softcursor encoding |
| 30 |
* |
| 31 |
*/ |
| 32 |
|
| 33 |
/* |
| 34 |
* desktop.c - functions to deal with "desktop" window. |
| 35 |
*/ |
| 36 |
|
| 37 |
#include <X11/Xlib.h> |
| 38 |
#include <sys/ipc.h> |
| 39 |
#include <sys/shm.h> |
| 40 |
#include <X11/extensions/XShm.h> |
| 41 |
#include <math.h> |
| 42 |
#include <limits.h> |
| 43 |
#include "vncviewer.h" |
| 44 |
|
| 45 |
static XShmSegmentInfo shminfo; |
| 46 |
static Bool caughtShmError = False; |
| 47 |
static Bool needShmCleanup = False; |
| 48 |
|
| 49 |
static XShmSegmentInfo zoomshminfo; |
| 50 |
static Bool caughtZoomShmError = False; |
| 51 |
static Bool needZoomShmCleanup = False; |
| 52 |
|
| 53 |
static Bool gcInited = False; |
| 54 |
GC gc; |
| 55 |
GC srcGC, dstGC; /* used for debugging copyrect */ |
| 56 |
Dimension dpyWidth, dpyHeight; |
| 57 |
|
| 58 |
static XImage *image = NULL; |
| 59 |
Bool useShm = True; |
| 60 |
|
| 61 |
static Bool zoomActive = False; |
| 62 |
static int zoomWidth, zoomHeight; |
| 63 |
static XImage *zoomImage = NULL; |
| 64 |
static Bool useZoomShm = True; |
| 65 |
|
| 66 |
/* for softcursor */ |
| 67 |
static char *savedArea = NULL; |
| 68 |
|
| 69 |
typedef enum { |
| 70 |
SOFTCURSOR_UNDER, |
| 71 |
SOFTCURSOR_PART_UNDER, |
| 72 |
SOFTCURSOR_UNAFFECTED |
| 73 |
} SoftCursorState; |
| 74 |
|
| 75 |
typedef int Sint32; |
| 76 |
typedef short Sint16; |
| 77 |
typedef char Sint8; |
| 78 |
typedef unsigned int Uint32; |
| 79 |
typedef unsigned short Uint16; |
| 80 |
typedef unsigned char Uint8; |
| 81 |
|
| 82 |
typedef struct { |
| 83 |
int w, h; |
| 84 |
unsigned int pitch; |
| 85 |
void *pixels; |
| 86 |
int BytesPerPixel; |
| 87 |
} Surface; |
| 88 |
|
| 89 |
typedef struct { |
| 90 |
Sint16 x, y; |
| 91 |
Uint16 w, h; |
| 92 |
} Rect; |
| 93 |
|
| 94 |
static void bgr233cpy(CARD8 *dst, CARD8 *src, int len); |
| 95 |
static void CopyDataToScreenRaw(char *buf, int x, int y, int width, int height); |
| 96 |
static void CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width,int height); |
| 97 |
static void FillRectangleBGR233(CARD8 buf, int x, int y, int width,int height); |
| 98 |
static int CheckRectangle(int x, int y, int width, int height); |
| 99 |
static SoftCursorState getSoftCursorState(int x, int y, int width, int height); |
| 100 |
static void discardCursorSavedArea(void); |
| 101 |
static void saveCursorSavedArea(void); |
| 102 |
|
| 103 |
static void ZoomInit(void); |
| 104 |
static void transformZoomSrc(int six, int siy, int siw, int sih, |
| 105 |
int *dix, int *diy, int *diw, int *dih, |
| 106 |
int srcW, int dstW, int srcH, int dstH); |
| 107 |
static void transformZoomDst(int *six, int *siy, int *siw, int *sih, |
| 108 |
int dix, int diy, int diw, int dih, |
| 109 |
int srcW, int dstW, int srcH, int dstH); |
| 110 |
static void ZoomSurfaceSrcCoords(int x, int y, int w, int h, |
| 111 |
int *dix, int *diy, int *diw, int *dih, |
| 112 |
Surface * src, Surface * dst); |
| 113 |
static void ZoomSurfaceCoords32(int sx, int sy, int sw, int sh, |
| 114 |
int dx, int dy, Surface * src, Surface * dst); |
| 115 |
static void sge_transform(Surface *src, Surface *dst, float xscale, float yscale, |
| 116 |
Uint16 qx, Uint16 qy); |
| 117 |
|
| 118 |
|
| 119 |
void |
| 120 |
DesktopInit(Window win) |
| 121 |
{ |
| 122 |
XGCValues gcv; |
| 123 |
|
| 124 |
image = CreateShmImage(); |
| 125 |
|
| 126 |
if (!image) { |
| 127 |
useShm = False; |
| 128 |
image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL, |
| 129 |
si.framebufferWidth, si.framebufferHeight, |
| 130 |
BitmapPad(dpy), 0); |
| 131 |
|
| 132 |
image->data = calloc(image->bytes_per_line * image->height, 1); |
| 133 |
if (!image->data) { |
| 134 |
fprintf(stderr,"malloc failed\n"); |
| 135 |
exit(1); |
| 136 |
} |
| 137 |
} |
| 138 |
|
| 139 |
gc = XCreateGC(dpy,win,0,NULL); |
| 140 |
|
| 141 |
gcv.function = GXxor; |
| 142 |
gcv.foreground = 0x0f0f0f0f; |
| 143 |
srcGC = XCreateGC(dpy,win,GCFunction|GCForeground,&gcv); |
| 144 |
gcv.foreground = 0xf0f0f0f0; |
| 145 |
dstGC = XCreateGC(dpy,win,GCFunction|GCForeground,&gcv); |
| 146 |
gcInited = True; |
| 147 |
} |
| 148 |
|
| 149 |
/* |
| 150 |
* DrawScreenRegionX11Thread |
| 151 |
* Never call from any other desktop.c function, only for X11 thread |
| 152 |
*/ |
| 153 |
|
| 154 |
void |
| 155 |
DrawScreenRegionX11Thread(Window win, int x, int y, int width, int height) { |
| 156 |
zoomActive = False; |
| 157 |
zoomWidth = 0; |
| 158 |
zoomHeight = 0; |
| 159 |
|
| 160 |
if (!image) |
| 161 |
return; |
| 162 |
|
| 163 |
if (useShm) |
| 164 |
XShmPutImage(dpy, win, gc, image, x, y, x, y, width, height, False); |
| 165 |
else |
| 166 |
XPutImage(dpy, win, gc, image, x, y, x, y, width, height); |
| 167 |
} |
| 168 |
|
| 169 |
/* |
| 170 |
* CheckRectangle |
| 171 |
*/ |
| 172 |
|
| 173 |
static int CheckRectangle(int x, int y, int width, int height) { |
| 174 |
if ((x < 0) || (y < 0)) |
| 175 |
return 0; |
| 176 |
|
| 177 |
if (((x+width) > si.framebufferWidth) || ((y+height) > si.framebufferHeight)) |
| 178 |
return 0; |
| 179 |
|
| 180 |
return 1; |
| 181 |
} |
| 182 |
|
| 183 |
static |
| 184 |
void bgr233cpy(CARD8 *dst, CARD8 *src, int len) { |
| 185 |
int i; |
| 186 |
CARD16 *d16; |
| 187 |
CARD32 *d32; |
| 188 |
|
| 189 |
switch (visbpp) { |
| 190 |
case 8: |
| 191 |
for (i = 0; i < len; i++) |
| 192 |
*(dst++) = (CARD8) BGR233ToPixel[*(src++)]; |
| 193 |
break; |
| 194 |
case 16: |
| 195 |
d16 = (CARD16*) dst; |
| 196 |
for (i = 0; i < len; i++) |
| 197 |
*(d16++) = (CARD16) BGR233ToPixel[*(src++)]; |
| 198 |
break; |
| 199 |
case 32: |
| 200 |
d32 = (CARD32*) dst; |
| 201 |
for (i = 0; i < len; i++) |
| 202 |
*(d32++) = (CARD32) BGR233ToPixel[*(src++)]; |
| 203 |
break; |
| 204 |
default: |
| 205 |
fprintf(stderr, "Unsupported softcursor depth %d\n", visbpp); |
| 206 |
} |
| 207 |
} |
| 208 |
|
| 209 |
|
| 210 |
/* |
| 211 |
* CopyDataToScreen. |
| 212 |
*/ |
| 213 |
|
| 214 |
void |
| 215 |
CopyDataToScreen(char *buf, int x, int y, int width, int height) |
| 216 |
{ |
| 217 |
SoftCursorState s; |
| 218 |
|
| 219 |
if (!CheckRectangle(x, y, width, height)) |
| 220 |
return; |
| 221 |
|
| 222 |
LockFramebuffer(); |
| 223 |
s = getSoftCursorState(x, y, width, height); |
| 224 |
if (s == SOFTCURSOR_PART_UNDER) |
| 225 |
undrawCursor(); |
| 226 |
|
| 227 |
if (!appData.useBGR233) |
| 228 |
CopyDataToScreenRaw(buf, x, y, width, height); |
| 229 |
else |
| 230 |
CopyBGR233ToScreen((CARD8 *)buf, x, y, width, height); |
| 231 |
|
| 232 |
if (s != SOFTCURSOR_UNAFFECTED) |
| 233 |
drawCursor(); |
| 234 |
|
| 235 |
UnlockFramebuffer(); |
| 236 |
SyncScreenRegion(x, y, width, height); |
| 237 |
} |
| 238 |
|
| 239 |
/* |
| 240 |
* CopyDataToScreenRaw. |
| 241 |
*/ |
| 242 |
|
| 243 |
static void |
| 244 |
CopyDataToScreenRaw(char *buf, int x, int y, int width, int height) |
| 245 |
{ |
| 246 |
int h; |
| 247 |
int widthInBytes = width * visbpp / 8; |
| 248 |
int scrWidthInBytes = image->bytes_per_line; |
| 249 |
char *scr = (image->data + y * scrWidthInBytes |
| 250 |
+ x * visbpp / 8); |
| 251 |
|
| 252 |
for (h = 0; h < height; h++) { |
| 253 |
memcpy(scr, buf, widthInBytes); |
| 254 |
buf += widthInBytes; |
| 255 |
scr += scrWidthInBytes; |
| 256 |
} |
| 257 |
} |
| 258 |
|
| 259 |
/* |
| 260 |
* CopyBGR233ToScreen. |
| 261 |
*/ |
| 262 |
|
| 263 |
static void |
| 264 |
CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width, int height) |
| 265 |
{ |
| 266 |
int p, q; |
| 267 |
int xoff = 7 - (x & 7); |
| 268 |
int xcur; |
| 269 |
int fbwb = si.framebufferWidth / 8; |
| 270 |
CARD8 *scr1 = ((CARD8 *)image->data) + y * fbwb + x / 8; |
| 271 |
CARD8 *scrt; |
| 272 |
CARD8 *scr8 = ((CARD8 *)image->data) + y * si.framebufferWidth + x; |
| 273 |
CARD16 *scr16 = ((CARD16 *)image->data) + y * si.framebufferWidth + x; |
| 274 |
CARD32 *scr32 = ((CARD32 *)image->data) + y * si.framebufferWidth + x; |
| 275 |
|
| 276 |
switch (visbpp) { |
| 277 |
|
| 278 |
/* thanks to Chris Hooper for single bpp support */ |
| 279 |
|
| 280 |
case 1: |
| 281 |
for (q = 0; q < height; q++) { |
| 282 |
xcur = xoff; |
| 283 |
scrt = scr1; |
| 284 |
for (p = 0; p < width; p++) { |
| 285 |
*scrt = ((*scrt & ~(1 << xcur)) |
| 286 |
| (BGR233ToPixel[*(buf++)] << xcur)); |
| 287 |
|
| 288 |
if (xcur-- == 0) { |
| 289 |
xcur = 7; |
| 290 |
scrt++; |
| 291 |
} |
| 292 |
} |
| 293 |
scr1 += fbwb; |
| 294 |
} |
| 295 |
break; |
| 296 |
|
| 297 |
case 8: |
| 298 |
for (q = 0; q < height; q++) { |
| 299 |
for (p = 0; p < width; p++) { |
| 300 |
*(scr8++) = BGR233ToPixel[*(buf++)]; |
| 301 |
} |
| 302 |
scr8 += si.framebufferWidth - width; |
| 303 |
} |
| 304 |
break; |
| 305 |
|
| 306 |
case 16: |
| 307 |
for (q = 0; q < height; q++) { |
| 308 |
for (p = 0; p < width; p++) { |
| 309 |
*(scr16++) = BGR233ToPixel[*(buf++)]; |
| 310 |
} |
| 311 |
scr16 += si.framebufferWidth - width; |
| 312 |
} |
| 313 |
break; |
| 314 |
|
| 315 |
case 32: |
| 316 |
for (q = 0; q < height; q++) { |
| 317 |
for (p = 0; p < width; p++) { |
| 318 |
*(scr32++) = BGR233ToPixel[*(buf++)]; |
| 319 |
} |
| 320 |
scr32 += si.framebufferWidth - width; |
| 321 |
} |
| 322 |
break; |
| 323 |
} |
| 324 |
} |
| 325 |
|
| 326 |
/* |
| 327 |
* FillRectangle8. |
| 328 |
*/ |
| 329 |
|
| 330 |
void |
| 331 |
FillRectangle8(CARD8 fg, int x, int y, int width, int height) |
| 332 |
{ |
| 333 |
SoftCursorState s; |
| 334 |
|
| 335 |
if (!CheckRectangle(x, y, width, height)) |
| 336 |
return; |
| 337 |
|
| 338 |
s = getSoftCursorState(x, y, width, height); |
| 339 |
if (s == SOFTCURSOR_PART_UNDER) |
| 340 |
undrawCursor(); |
| 341 |
|
| 342 |
if (!appData.useBGR233) { |
| 343 |
int h; |
| 344 |
int widthInBytes = width * visbpp / 8; |
| 345 |
int scrWidthInBytes = image->bytes_per_line; |
| 346 |
|
| 347 |
char *scr = (image->data + y * scrWidthInBytes |
| 348 |
+ x * visbpp / 8); |
| 349 |
|
| 350 |
for (h = 0; h < height; h++) { |
| 351 |
memset(scr, fg, widthInBytes); |
| 352 |
scr += scrWidthInBytes; |
| 353 |
} |
| 354 |
} else { |
| 355 |
FillRectangleBGR233(fg, x, y, width, height); |
| 356 |
} |
| 357 |
|
| 358 |
if (s != SOFTCURSOR_UNAFFECTED) |
| 359 |
drawCursor(); |
| 360 |
} |
| 361 |
|
| 362 |
/* |
| 363 |
* FillRectangleBGR233. |
| 364 |
*/ |
| 365 |
|
| 366 |
static void |
| 367 |
FillRectangleBGR233(CARD8 fg, int x, int y, int width, int height) |
| 368 |
{ |
| 369 |
int p, q; |
| 370 |
int xoff = 7 - (x & 7); |
| 371 |
int xcur; |
| 372 |
int fbwb = si.framebufferWidth / 8; |
| 373 |
CARD8 *scr1 = ((CARD8 *)image->data) + y * fbwb + x / 8; |
| 374 |
CARD8 *scrt; |
| 375 |
CARD8 *scr8 = ((CARD8 *)image->data) + y * si.framebufferWidth + x; |
| 376 |
CARD16 *scr16 = ((CARD16 *)image->data) + y * si.framebufferWidth + x; |
| 377 |
CARD32 *scr32 = ((CARD32 *)image->data) + y * si.framebufferWidth + x; |
| 378 |
|
| 379 |
unsigned long fg233 = BGR233ToPixel[fg]; |
| 380 |
|
| 381 |
switch (visbpp) { |
| 382 |
|
| 383 |
/* thanks to Chris Hooper for single bpp support */ |
| 384 |
|
| 385 |
case 1: |
| 386 |
for (q = 0; q < height; q++) { |
| 387 |
xcur = xoff; |
| 388 |
scrt = scr1; |
| 389 |
for (p = 0; p < width; p++) { |
| 390 |
*scrt = ((*scrt & ~(1 << xcur)) |
| 391 |
| (fg233 << xcur)); |
| 392 |
|
| 393 |
if (xcur-- == 0) { |
| 394 |
xcur = 7; |
| 395 |
scrt++; |
| 396 |
} |
| 397 |
} |
| 398 |
scr1 += fbwb; |
| 399 |
} |
| 400 |
break; |
| 401 |
|
| 402 |
case 8: |
| 403 |
for (q = 0; q < height; q++) { |
| 404 |
for (p = 0; p < width; p++) { |
| 405 |
*(scr8++) = fg233; |
| 406 |
} |
| 407 |
scr8 += si.framebufferWidth - width; |
| 408 |
} |
| 409 |
break; |
| 410 |
|
| 411 |
case 16: |
| 412 |
for (q = 0; q < height; q++) { |
| 413 |
for (p = 0; p < width; p++) { |
| 414 |
*(scr16++) = fg233; |
| 415 |
} |
| 416 |
scr16 += si.framebufferWidth - width; |
| 417 |
} |
| 418 |
break; |
| 419 |
|
| 420 |
case 32: |
| 421 |
for (q = 0; q < height; q++) { |
| 422 |
for (p = 0; p < width; p++) { |
| 423 |
*(scr32++) = fg233; |
| 424 |
} |
| 425 |
scr32 += si.framebufferWidth - width; |
| 426 |
} |
| 427 |
break; |
| 428 |
} |
| 429 |
} |
| 430 |
|
| 431 |
/* |
| 432 |
* FillRectangle16 |
| 433 |
*/ |
| 434 |
|
| 435 |
void |
| 436 |
FillRectangle16(CARD16 fg, int x, int y, int width, int height) |
| 437 |
{ |
| 438 |
int i, h; |
| 439 |
int scrWidthInBytes = image->bytes_per_line; |
| 440 |
|
| 441 |
char *scr = (image->data + y * scrWidthInBytes |
| 442 |
+ x * visbpp / 8); |
| 443 |
CARD16 *scr16; |
| 444 |
SoftCursorState s; |
| 445 |
|
| 446 |
if (!CheckRectangle(x, y, width, height)) |
| 447 |
return; |
| 448 |
|
| 449 |
s = getSoftCursorState(x, y, width, height); |
| 450 |
if (s == SOFTCURSOR_PART_UNDER) |
| 451 |
undrawCursor(); |
| 452 |
|
| 453 |
for (h = 0; h < height; h++) { |
| 454 |
scr16 = (CARD16*) scr; |
| 455 |
for (i = 0; i < width; i++) |
| 456 |
scr16[i] = fg; |
| 457 |
scr += scrWidthInBytes; |
| 458 |
} |
| 459 |
|
| 460 |
if (s != SOFTCURSOR_UNAFFECTED) |
| 461 |
drawCursor(); |
| 462 |
} |
| 463 |
|
| 464 |
/* |
| 465 |
* FillRectangle32 |
| 466 |
*/ |
| 467 |
|
| 468 |
void |
| 469 |
FillRectangle32(CARD32 fg, int x, int y, int width, int height) |
| 470 |
{ |
| 471 |
int i, h; |
| 472 |
int scrWidthInBytes = image->bytes_per_line; |
| 473 |
SoftCursorState s; |
| 474 |
|
| 475 |
char *scr = (image->data + y * scrWidthInBytes |
| 476 |
+ x * visbpp / 8); |
| 477 |
CARD32 *scr32; |
| 478 |
|
| 479 |
if (!CheckRectangle(x, y, width, height)) |
| 480 |
return; |
| 481 |
|
| 482 |
s = getSoftCursorState(x, y, width, height); |
| 483 |
if (s == SOFTCURSOR_PART_UNDER) |
| 484 |
undrawCursor(); |
| 485 |
|
| 486 |
for (h = 0; h < height; h++) { |
| 487 |
scr32 = (CARD32*) scr; |
| 488 |
for (i = 0; i < width; i++) |
| 489 |
scr32[i] = fg; |
| 490 |
scr += scrWidthInBytes; |
| 491 |
} |
| 492 |
|
| 493 |
if (s != SOFTCURSOR_UNAFFECTED) |
| 494 |
drawCursor(); |
| 495 |
} |
| 496 |
|
| 497 |
/* |
| 498 |
* CopyDataFromScreen. |
| 499 |
*/ |
| 500 |
|
| 501 |
void |
| 502 |
CopyDataFromScreen(char *buf, int x, int y, int width, int height) |
| 503 |
{ |
| 504 |
int widthInBytes = width * visbpp / 8; |
| 505 |
int scrWidthInBytes = image->bytes_per_line; |
| 506 |
char *src = (image->data + y * scrWidthInBytes |
| 507 |
+ x * visbpp / 8); |
| 508 |
int h; |
| 509 |
|
| 510 |
if (!CheckRectangle(x, y, width, height)) |
| 511 |
return; |
| 512 |
|
| 513 |
for (h = 0; h < height; h++) { |
| 514 |
memcpy(buf, src, widthInBytes); |
| 515 |
src += scrWidthInBytes; |
| 516 |
buf += widthInBytes; |
| 517 |
} |
| 518 |
} |
| 519 |
|
| 520 |
/* |
| 521 |
* CopyArea |
| 522 |
*/ |
| 523 |
|
| 524 |
void |
| 525 |
CopyArea(int srcX, int srcY, int width, int height, int x, int y) |
| 526 |
{ |
| 527 |
int widthInBytes = width * visbpp / 8; |
| 528 |
SoftCursorState sSrc, sDst; |
| 529 |
|
| 530 |
LockFramebuffer(); |
| 531 |
sSrc = getSoftCursorState(srcX, srcY, width, height); |
| 532 |
sDst = getSoftCursorState(x, y, width, height); |
| 533 |
if ((sSrc != SOFTCURSOR_UNAFFECTED) || |
| 534 |
(sDst == SOFTCURSOR_PART_UNDER)) |
| 535 |
undrawCursor(); |
| 536 |
|
| 537 |
if ((srcY+height < y) || (y+height < srcY) || |
| 538 |
(srcX+width < x) || (x+width < srcX)) { |
| 539 |
|
| 540 |
int scrWidthInBytes = image->bytes_per_line; |
| 541 |
char *src = (image->data + srcY * scrWidthInBytes |
| 542 |
+ srcX * visbpp / 8); |
| 543 |
char *dst = (image->data + y * scrWidthInBytes |
| 544 |
+ x * visbpp / 8); |
| 545 |
int h; |
| 546 |
|
| 547 |
if (!CheckRectangle(srcX, srcY, width, height)) { |
| 548 |
UnlockFramebuffer(); |
| 549 |
return; |
| 550 |
} |
| 551 |
if (!CheckRectangle(x, y, width, height)) { |
| 552 |
UnlockFramebuffer(); |
| 553 |
return; |
| 554 |
} |
| 555 |
|
| 556 |
for (h = 0; h < height; h++) { |
| 557 |
memcpy(dst, src, widthInBytes); |
| 558 |
src += scrWidthInBytes; |
| 559 |
dst += scrWidthInBytes; |
| 560 |
} |
| 561 |
} |
| 562 |
else { |
| 563 |
char *buf = malloc(widthInBytes*height); |
| 564 |
if (!buf) { |
| 565 |
UnlockFramebuffer(); |
| 566 |
fprintf(stderr, "Out of memory, CopyArea impossible\n"); |
| 567 |
return; |
| 568 |
} |
| 569 |
CopyDataFromScreen(buf, srcX, srcY, width, height); |
| 570 |
CopyDataToScreenRaw(buf, x, y, width, height); |
| 571 |
free(buf); |
| 572 |
} |
| 573 |
if ((sSrc != SOFTCURSOR_UNAFFECTED) || |
| 574 |
(sDst != SOFTCURSOR_UNAFFECTED)) |
| 575 |
drawCursor(); |
| 576 |
UnlockFramebuffer(); |
| 577 |
SyncScreenRegion(x, y, width, height); |
| 578 |
} |
| 579 |
|
| 580 |
void SyncScreenRegion(int x, int y, int width, int height) { |
| 581 |
int dx, dy, dw, dh; |
| 582 |
|
| 583 |
if (zoomActive) { |
| 584 |
Surface src, dest; |
| 585 |
src.w = si.framebufferWidth; |
| 586 |
src.h = si.framebufferHeight; |
| 587 |
src.pitch = image->bytes_per_line; |
| 588 |
src.pixels = image->data; |
| 589 |
src.BytesPerPixel = visbpp / 8; |
| 590 |
dest.w = zoomWidth; |
| 591 |
dest.h = zoomHeight; |
| 592 |
dest.pitch = zoomImage->bytes_per_line; |
| 593 |
dest.pixels = zoomImage->data; |
| 594 |
dest.BytesPerPixel = visbpp / 8; |
| 595 |
ZoomSurfaceSrcCoords(x, y, width, height, &dx, &dy, &dw, &dh, &src, &dest); |
| 596 |
} |
| 597 |
else { |
| 598 |
dx = x; dy = y; |
| 599 |
dw = width; dh = height; |
| 600 |
} |
| 601 |
DrawScreenRegion(dx, dy, dw, dh); |
| 602 |
} |
| 603 |
|
| 604 |
void SyncScreenRegionX11Thread(int x, int y, int width, int height) { |
| 605 |
int dx, dy, dw, dh; |
| 606 |
|
| 607 |
if (zoomActive) { |
| 608 |
Surface src, dest; |
| 609 |
src.w = si.framebufferWidth; |
| 610 |
src.h = si.framebufferHeight; |
| 611 |
src.pitch = image->bytes_per_line; |
| 612 |
src.pixels = image->data; |
| 613 |
src.BytesPerPixel = visbpp / 8; |
| 614 |
dest.w = zoomWidth; |
| 615 |
dest.h = zoomHeight; |
| 616 |
dest.pitch = zoomImage->bytes_per_line; |
| 617 |
dest.pixels = zoomImage->data; |
| 618 |
dest.BytesPerPixel = visbpp / 8; |
| 619 |
ZoomSurfaceSrcCoords(x, y, width, height, &dx, &dy, &dw, &dh, &src, &dest); |
| 620 |
} |
| 621 |
else { |
| 622 |
dx = x; dy = y; |
| 623 |
dw = width; dh = height; |
| 624 |
} |
| 625 |
DrawAnyScreenRegionX11Thread(dx, dy, dw, dh); |
| 626 |
} |
| 627 |
|
| 628 |
/* |
| 629 |
* ToplevelInitBeforeRealization sets the title, geometry and other resources |
| 630 |
* on the toplevel window. |
| 631 |
*/ |
| 632 |
|
| 633 |
void |
| 634 |
ToplevelInit() |
| 635 |
{ |
| 636 |
dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy)); |
| 637 |
dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy)); |
| 638 |
} |
| 639 |
|
| 640 |
/* |
| 641 |
* Cleanup - perform shm cleanup operations prior to exiting. |
| 642 |
*/ |
| 643 |
|
| 644 |
void |
| 645 |
Cleanup() |
| 646 |
{ |
| 647 |
if (useShm || useZoomShm) |
| 648 |
ShmCleanup(); |
| 649 |
} |
| 650 |
|
| 651 |
void |
| 652 |
ShmCleanup() |
| 653 |
{ |
| 654 |
fprintf(stderr,"ShmCleanup called\n"); |
| 655 |
if (needShmCleanup) { |
| 656 |
shmdt(shminfo.shmaddr); |
| 657 |
shmctl(shminfo.shmid, IPC_RMID, 0); |
| 658 |
needShmCleanup = False; |
| 659 |
} |
| 660 |
if (needZoomShmCleanup) { |
| 661 |
shmdt(zoomshminfo.shmaddr); |
| 662 |
shmctl(zoomshminfo.shmid, IPC_RMID, 0); |
| 663 |
needZoomShmCleanup = False; |
| 664 |
} |
| 665 |
} |
| 666 |
|
| 667 |
static int |
| 668 |
ShmCreationXErrorHandler(Display *d, XErrorEvent *e) |
| 669 |
{ |
| 670 |
caughtShmError = True; |
| 671 |
return 0; |
| 672 |
} |
| 673 |
|
| 674 |
XImage * |
| 675 |
CreateShmImage() |
| 676 |
{ |
| 677 |
XImage *_image; |
| 678 |
XErrorHandler oldXErrorHandler; |
| 679 |
|
| 680 |
if (!XShmQueryExtension(dpy)) |
| 681 |
return NULL; |
| 682 |
|
| 683 |
_image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo, |
| 684 |
si.framebufferWidth, si.framebufferHeight); |
| 685 |
if (!_image) return NULL; |
| 686 |
|
| 687 |
shminfo.shmid = shmget(IPC_PRIVATE, |
| 688 |
_image->bytes_per_line * _image->height, |
| 689 |
IPC_CREAT|0777); |
| 690 |
|
| 691 |
if (shminfo.shmid == -1) { |
| 692 |
XDestroyImage(_image); |
| 693 |
return NULL; |
| 694 |
} |
| 695 |
|
| 696 |
shminfo.shmaddr = _image->data = shmat(shminfo.shmid, 0, 0); |
| 697 |
|
| 698 |
if (shminfo.shmaddr == (char *)-1) { |
| 699 |
XDestroyImage(_image); |
| 700 |
shmctl(shminfo.shmid, IPC_RMID, 0); |
| 701 |
return NULL; |
| 702 |
} |
| 703 |
|
| 704 |
shminfo.readOnly = True; |
| 705 |
|
| 706 |
oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler); |
| 707 |
XShmAttach(dpy, &shminfo); |
| 708 |
XSync(dpy, False); |
| 709 |
XSetErrorHandler(oldXErrorHandler); |
| 710 |
|
| 711 |
if (caughtShmError) { |
| 712 |
XDestroyImage(_image); |
| 713 |
shmdt(shminfo.shmaddr); |
| 714 |
shmctl(shminfo.shmid, IPC_RMID, 0); |
| 715 |
return NULL; |
| 716 |
} |
| 717 |
|
| 718 |
needShmCleanup = True; |
| 719 |
|
| 720 |
fprintf(stderr,"Using shared memory PutImage\n"); |
| 721 |
|
| 722 |
return _image; |
| 723 |
} |
| 724 |
|
| 725 |
void undrawCursor() { |
| 726 |
int x, y, w, h; |
| 727 |
|
| 728 |
if ((imageIndex < 0) || !savedArea) |
| 729 |
return; |
| 730 |
|
| 731 |
getBoundingRectCursor(cursorX, cursorY, imageIndex, |
| 732 |
&x, &y, &w, &h); |
| 733 |
|
| 734 |
if ((w < 1) || (h < 1)) |
| 735 |
return; |
| 736 |
|
| 737 |
CopyDataToScreenRaw(savedArea, x, y, w, h); |
| 738 |
discardCursorSavedArea(); |
| 739 |
} |
| 740 |
|
| 741 |
static void drawCursorImage() { |
| 742 |
int x, y, w, h, pw, pixelsLeft, processingMask; |
| 743 |
int skipLeft, skipRight; |
| 744 |
PointerImage *pi = &pointerImages[imageIndex]; |
| 745 |
CARD8 *img = (CARD8*) pi->image; |
| 746 |
CARD8 *imgEnd = &img[pi->len]; |
| 747 |
CARD8 *fb; |
| 748 |
|
| 749 |
/* check whether the source image has ended (image broken) */ |
| 750 |
#define CHECK_IMG(x) if (&img[x] > imgEnd) goto imgError |
| 751 |
|
| 752 |
/* check whether the end of the framebuffer has been reached (last line) */ |
| 753 |
#define CHECK_END() if ((wl == 0) && (h == 1)) return |
| 754 |
|
| 755 |
/* skip x pixels in the source (x must be < pixelsLeft!) */ |
| 756 |
#define SKIP_IMG(x) if ((x > 0) && !processingMask) { \ |
| 757 |
CHECK_END(); \ |
| 758 |
img += pw * x; \ |
| 759 |
CHECK_IMG(0); \ |
| 760 |
} |
| 761 |
|
| 762 |
/* skip x pixels in source and destination */ |
| 763 |
#define SKIP_PIXELS(x) { int wl = x; \ |
| 764 |
while (pixelsLeft <= wl) { \ |
| 765 |
wl -= pixelsLeft; \ |
| 766 |
SKIP_IMG(pixelsLeft); \ |
| 767 |
CHECK_END(); \ |
| 768 |
pixelsLeft = *(img++); \ |
| 769 |
CHECK_IMG(0); \ |
| 770 |
processingMask = processingMask ? 0 : 1; \ |
| 771 |
} \ |
| 772 |
pixelsLeft -= wl; \ |
| 773 |
SKIP_IMG(wl); \ |
| 774 |
} |
| 775 |
|
| 776 |
if (!img) |
| 777 |
return; |
| 778 |
|
| 779 |
x = cursorX - pi->hotX; |
| 780 |
y = cursorY - pi->hotY; |
| 781 |
w = pi->w; |
| 782 |
h = pi->h; |
| 783 |
|
| 784 |
if (!rectsIntersect(x, y, w, h, |
| 785 |
0, 0, si.framebufferWidth, si.framebufferHeight)) { |
| 786 |
fprintf(stderr, "intersect abort\n"); |
| 787 |
return; |
| 788 |
} |
| 789 |
|
| 790 |
pw = myFormat.bitsPerPixel / 8; |
| 791 |
processingMask = 1; |
| 792 |
pixelsLeft = *(img++); |
| 793 |
|
| 794 |
/* at this point everything is initialized for the macros */ |
| 795 |
|
| 796 |
/* skip/clip bottom lines */ |
| 797 |
if ((y+h) > si.framebufferHeight) |
| 798 |
h = si.framebufferHeight - y; |
| 799 |
|
| 800 |
/* Skip invisible top lines */ |
| 801 |
while (y < 0) { |
| 802 |
SKIP_PIXELS(w); |
| 803 |
y++; |
| 804 |
h--; |
| 805 |
} |
| 806 |
|
| 807 |
/* calculate left/right clipping */ |
| 808 |
if (x < 0) { |
| 809 |
skipLeft = -x; |
| 810 |
w += x; |
| 811 |
x = 0; |
| 812 |
} |
| 813 |
else |
| 814 |
skipLeft = 0; |
| 815 |
|
| 816 |
if ((x+w) > si.framebufferWidth) { |
| 817 |
skipRight = (x+w) - si.framebufferWidth; |
| 818 |
w = si.framebufferWidth - x; |
| 819 |
} |
| 820 |
else |
| 821 |
skipRight = 0; |
| 822 |
|
| 823 |
fb = (CARD8*) image->data + y * image->bytes_per_line + x * visbpp / 8; |
| 824 |
|
| 825 |
/* Paint the thing */ |
| 826 |
while (h > 0) { |
| 827 |
SKIP_PIXELS(skipLeft); |
| 828 |
|
| 829 |
{ |
| 830 |
CARD8 *fbx = fb; |
| 831 |
int wl = w; |
| 832 |
while (pixelsLeft <= wl) { |
| 833 |
wl -= pixelsLeft; |
| 834 |
if ((pixelsLeft > 0) && !processingMask) { |
| 835 |
int pl = pw * pixelsLeft; |
| 836 |
CHECK_IMG(pl); |
| 837 |
if (!appData.useBGR233) |
| 838 |
memcpy(fbx, img, pl); |
| 839 |
else |
| 840 |
bgr233cpy(fbx, img, pixelsLeft); |
| 841 |
img += pl; |
| 842 |
} |
| 843 |
|
| 844 |
CHECK_END(); |
| 845 |
fbx += pixelsLeft * visbpp / 8; |
| 846 |
pixelsLeft = *(img++); |
| 847 |
|
| 848 |
CHECK_IMG(0); |
| 849 |
processingMask = processingMask ? 0 : 1; |
| 850 |
} |
| 851 |
pixelsLeft -= wl; |
| 852 |
if ((wl > 0) && !processingMask) { |
| 853 |
int pl = pw * wl; |
| 854 |
CHECK_IMG(pl); |
| 855 |
if (!appData.useBGR233) |
| 856 |
memcpy(fbx, img, pl); |
| 857 |
else |
| 858 |
bgr233cpy(fbx, img, wl); |
| 859 |
img += pl; |
| 860 |
} |
| 861 |
} |
| 862 |
|
| 863 |
SKIP_PIXELS(skipRight); |
| 864 |
fb += image->bytes_per_line; |
| 865 |
h--; |
| 866 |
} |
| 867 |
return; |
| 868 |
|
| 869 |
imgError: |
| 870 |
fprintf(stderr, "Error in softcursor image %d\n", imageIndex); |
| 871 |
pointerImages[imageIndex].set = 0; |
| 872 |
} |
| 873 |
|
| 874 |
static void discardCursorSavedArea() { |
| 875 |
if (savedArea) |
| 876 |
free(savedArea); |
| 877 |
savedArea = 0; |
| 878 |
} |
| 879 |
|
| 880 |
static void saveCursorSavedArea() { |
| 881 |
int x, y, w, h; |
| 882 |
|
| 883 |
if (imageIndex < 0) |
| 884 |
return; |
| 885 |
getBoundingRectCursor(cursorX, cursorY, imageIndex, |
| 886 |
&x, &y, &w, &h); |
| 887 |
if ((w < 1) || (h < 1)) |
| 888 |
return; |
| 889 |
discardCursorSavedArea(); |
| 890 |
savedArea = malloc(h*image->bytes_per_line); |
| 891 |
if (!savedArea) { |
| 892 |
fprintf(stderr,"malloc failed, saving cursor not possible\n"); |
| 893 |
exit(1); |
| 894 |
} |
| 895 |
CopyDataFromScreen(savedArea, x, y, w, h); |
| 896 |
} |
| 897 |
|
| 898 |
void drawCursor() { |
| 899 |
saveCursorSavedArea(); |
| 900 |
drawCursorImage(); |
| 901 |
} |
| 902 |
|
| 903 |
void getBoundingRectCursor(int cx, int cy, int _imageIndex, |
| 904 |
int *x, int *y, int *w, int *h) { |
| 905 |
int nx, ny, nw, nh; |
| 906 |
|
| 907 |
if ((_imageIndex < 0) || !pointerImages[_imageIndex].set) { |
| 908 |
*x = 0; |
| 909 |
*y = 0; |
| 910 |
*w = 0; |
| 911 |
*h = 0; |
| 912 |
return; |
| 913 |
} |
| 914 |
|
| 915 |
nx = cx - pointerImages[_imageIndex].hotX; |
| 916 |
ny = cy - pointerImages[_imageIndex].hotY; |
| 917 |
nw = pointerImages[_imageIndex].w; |
| 918 |
nh = pointerImages[_imageIndex].h; |
| 919 |
if (nx < 0) { |
| 920 |
nw += nx; |
| 921 |
nx = 0; |
| 922 |
} |
| 923 |
if (ny < 0) { |
| 924 |
nh += ny; |
| 925 |
ny = 0; |
| 926 |
} |
| 927 |
if ((nx+nw) > si.framebufferWidth) |
| 928 |
nw = si.framebufferWidth - nx; |
| 929 |
if ((ny+nh) > si.framebufferHeight) |
| 930 |
nh = si.framebufferHeight - ny; |
| 931 |
if ((nw <= 0) || (nh <= 0)) { |
| 932 |
*x = 0; |
| 933 |
*y = 0; |
| 934 |
*w = 0; |
| 935 |
*h = 0; |
| 936 |
return; |
| 937 |
} |
| 938 |
|
| 939 |
*x = nx; |
| 940 |
*y = ny; |
| 941 |
*w = nw; |
| 942 |
*h = nh; |
| 943 |
} |
| 944 |
|
| 945 |
static SoftCursorState getSoftCursorState(int x, int y, int w, int h) { |
| 946 |
int cx, cy, cw, ch; |
| 947 |
|
| 948 |
if (imageIndex < 0) |
| 949 |
return SOFTCURSOR_UNAFFECTED; |
| 950 |
|
| 951 |
getBoundingRectCursor(cursorX, cursorY, imageIndex, |
| 952 |
&cx, &cy, &cw, &ch); |
| 953 |
|
| 954 |
if ((cw == 0) || (ch == 0)) |
| 955 |
return SOFTCURSOR_UNAFFECTED; |
| 956 |
|
| 957 |
if (!rectsIntersect(x, y, w, h, cx, cy, cw, ch)) |
| 958 |
return SOFTCURSOR_UNAFFECTED; |
| 959 |
if (rectContains(x, y, w, h, cx, cy, cw, ch)) |
| 960 |
return SOFTCURSOR_UNDER; |
| 961 |
else |
| 962 |
return SOFTCURSOR_PART_UNDER; |
| 963 |
} |
| 964 |
|
| 965 |
int rectsIntersect(int x, int y, int w, int h, |
| 966 |
int x2, int y2, int w2, int h2) { |
| 967 |
if (x2 >= (x+w)) |
| 968 |
return 0; |
| 969 |
if (y2 >= (y+h)) |
| 970 |
return 0; |
| 971 |
if ((x2+w2) <= x) |
| 972 |
return 0; |
| 973 |
if ((y2+h2) <= y) |
| 974 |
return 0; |
| 975 |
return 1; |
| 976 |
} |
| 977 |
|
| 978 |
int rectContains(int outX, int outY, int outW, int outH, |
| 979 |
int inX, int inY, int inW, int inH) { |
| 980 |
if (inX < outX) |
| 981 |
return 0; |
| 982 |
if (inY < outY) |
| 983 |
return 0; |
| 984 |
if ((inX+inW) > (outX+outW)) |
| 985 |
return 0; |
| 986 |
if ((inY+inH) > (outY+outH)) |
| 987 |
return 0; |
| 988 |
return 1; |
| 989 |
} |
| 990 |
|
| 991 |
void rectsJoin(int *nx1, int *ny1, int *nw1, int *nh1, |
| 992 |
int x2, int y2, int w2, int h2) { |
| 993 |
int ox, oy, ow, oh; |
| 994 |
ox = *nx1; |
| 995 |
oy = *ny1; |
| 996 |
ow = *nw1; |
| 997 |
oh = *nh1; |
| 998 |
|
| 999 |
if (x2 < ox) { |
| 1000 |
ow += ox - x2; |
| 1001 |
ox = x2; |
| 1002 |
} |
| 1003 |
if (y2 < oy) { |
| 1004 |
oh += oy - y2; |
| 1005 |
oy = y2; |
| 1006 |
} |
| 1007 |
if ((x2+w2) > (ox+ow)) |
| 1008 |
ow = (x2+w2) - ox; |
| 1009 |
if ((y2+h2) > (oy+oh)) |
| 1010 |
oh = (y2+h2) - oy; |
| 1011 |
|
| 1012 |
*nx1 = ox; |
| 1013 |
*ny1 = oy; |
| 1014 |
*nw1 = ow; |
| 1015 |
*nh1 = oh; |
| 1016 |
} |
| 1017 |
|
| 1018 |
XImage * |
| 1019 |
CreateShmZoomImage() |
| 1020 |
{ |
| 1021 |
XImage *_image; |
| 1022 |
XErrorHandler oldXErrorHandler; |
| 1023 |
|
| 1024 |
if (!XShmQueryExtension(dpy)) |
| 1025 |
return NULL; |
| 1026 |
|
| 1027 |
_image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &zoomshminfo, |
| 1028 |
si.framebufferWidth, si.framebufferHeight); |
| 1029 |
if (!_image) return NULL; |
| 1030 |
|
| 1031 |
zoomshminfo.shmid = shmget(IPC_PRIVATE, |
| 1032 |
_image->bytes_per_line * _image->height, |
| 1033 |
IPC_CREAT|0777); |
| 1034 |
|
| 1035 |
if (zoomshminfo.shmid == -1) { |
| 1036 |
XDestroyImage(_image); |
| 1037 |
return NULL; |
| 1038 |
} |
| 1039 |
|
| 1040 |
zoomshminfo.shmaddr = _image->data = shmat(zoomshminfo.shmid, 0, 0); |
| 1041 |
|
| 1042 |
if (zoomshminfo.shmaddr == (char *)-1) { |
| 1043 |
XDestroyImage(_image); |
| 1044 |
shmctl(zoomshminfo.shmid, IPC_RMID, 0); |
| 1045 |
return NULL; |
| 1046 |
} |
| 1047 |
|
| 1048 |
zoomshminfo.readOnly = True; |
| 1049 |
|
| 1050 |
oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler); |
| 1051 |
XShmAttach(dpy, &zoomshminfo); |
| 1052 |
XSync(dpy, False); |
| 1053 |
XSetErrorHandler(oldXErrorHandler); |
| 1054 |
|
| 1055 |
if (caughtZoomShmError) { |
| 1056 |
XDestroyImage(_image); |
| 1057 |
shmdt(zoomshminfo.shmaddr); |
| 1058 |
shmctl(zoomshminfo.shmid, IPC_RMID, 0); |
| 1059 |
return NULL; |
| 1060 |
} |
| 1061 |
|
| 1062 |
needZoomShmCleanup = True; |
| 1063 |
|
| 1064 |
fprintf(stderr,"Using shared memory PutImage\n"); |
| 1065 |
|
| 1066 |
return _image; |
| 1067 |
} |
| 1068 |
|
| 1069 |
|
| 1070 |
/* |
| 1071 |
* DrawZoomedScreenRegionX11Thread |
| 1072 |
* Never call from any other desktop.c function, only for X11 thread |
| 1073 |
*/ |
| 1074 |
|
| 1075 |
void |
| 1076 |
DrawZoomedScreenRegionX11Thread(Window win, int zwidth, int zheight, |
| 1077 |
int x, int y, int width, int height) { |
| 1078 |
if (!image) |
| 1079 |
return; |
| 1080 |
|
| 1081 |
if (zwidth > si.framebufferWidth) |
| 1082 |
zwidth = si.framebufferWidth; |
| 1083 |
if (zheight > si.framebufferHeight) |
| 1084 |
zheight = si.framebufferHeight; |
| 1085 |
|
| 1086 |
if (!zoomActive) { |
| 1087 |
ZoomInit(); |
| 1088 |
zoomActive = True; |
| 1089 |
} |
| 1090 |
|
| 1091 |
if ((zoomWidth != zwidth) || (zoomHeight != zheight)) { |
| 1092 |
Surface src, dest; |
| 1093 |
|
| 1094 |
zoomWidth = zwidth; |
| 1095 |
zoomHeight = zheight; |
| 1096 |
|
| 1097 |
src.w = si.framebufferWidth; |
| 1098 |
src.h = si.framebufferHeight; |
| 1099 |
src.pitch = image->bytes_per_line; |
| 1100 |
src.pixels = image->data; |
| 1101 |
src.BytesPerPixel = visbpp / 8; |
| 1102 |
dest.w = zwidth; |
| 1103 |
dest.h = zheight; |
| 1104 |
dest.pitch = zoomImage->bytes_per_line; |
| 1105 |
dest.pixels = zoomImage->data; |
| 1106 |
dest.BytesPerPixel = visbpp / 8; |
| 1107 |
sge_transform(&src, &dest, |
| 1108 |
(float)dest.w/(float)src.w, (float)dest.h/(float)src.h, |
| 1109 |
0, 0); |
| 1110 |
|
| 1111 |
if (useZoomShm) |
| 1112 |
XShmPutImage(dpy, win, gc, zoomImage, 0, 0, 0, 0, zwidth, zheight, False); |
| 1113 |
else |
| 1114 |
XPutImage(dpy, win, gc, zoomImage, 0, 0, 0, 0, zwidth, zheight); |
| 1115 |
return; |
| 1116 |
} |
| 1117 |
|
| 1118 |
if (useZoomShm) |
| 1119 |
XShmPutImage(dpy, win, gc, zoomImage, x, y, x, y, width, height, False); |
| 1120 |
else |
| 1121 |
XPutImage(dpy, win, gc, zoomImage, x, y, x, y, width, height); |
| 1122 |
} |
| 1123 |
|
| 1124 |
|
| 1125 |
static void |
| 1126 |
ZoomInit() |
| 1127 |
{ |
| 1128 |
if (zoomImage) |
| 1129 |
return; |
| 1130 |
|
| 1131 |
zoomImage = CreateShmZoomImage(); |
| 1132 |
|
| 1133 |
if (!zoomImage) { |
| 1134 |
useZoomShm = False; |
| 1135 |
zoomImage = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL, |
| 1136 |
si.framebufferWidth, si.framebufferHeight, |
| 1137 |
BitmapPad(dpy), 0); |
| 1138 |
|
| 1139 |
zoomImage->data = calloc(zoomImage->bytes_per_line * zoomImage->height, 1); |
| 1140 |
if (!zoomImage->data) { |
| 1141 |
fprintf(stderr,"malloc failed\n"); |
| 1142 |
exit(1); |
| 1143 |
} |
| 1144 |
} |
| 1145 |
} |
| 1146 |
|
| 1147 |
static void transformZoomSrc(int six, int siy, int siw, int sih, |
| 1148 |
int *dix, int *diy, int *diw, int *dih, |
| 1149 |
int srcW, int dstW, int srcH, int dstH) { |
| 1150 |
double sx, sy, sw, sh; |
| 1151 |
double dx, dy, dw, dh; |
| 1152 |
double wq, hq; |
| 1153 |
|
| 1154 |
sx = six; sy = siy; |
| 1155 |
sw = siw; sh = sih; |
| 1156 |
|
| 1157 |
wq = ((double)dstW) / (double) srcW; |
| 1158 |
hq = ((double)dstH) / (double) srcH; |
| 1159 |
|
| 1160 |
dx = sx * wq; |
| 1161 |
dy = sy * hq; |
| 1162 |
dw = sw * wq; |
| 1163 |
dh = sh * hq; |
| 1164 |
|
| 1165 |
*dix = dx; |
| 1166 |
*diy = dy; |
| 1167 |
*diw = dw+(dx-(int)dx)+0.5; |
| 1168 |
*dih = dh+(dy-(int)dy)+0.5; |
| 1169 |
} |
| 1170 |
|
| 1171 |
static void transformZoomDst(int *six, int *siy, int *siw, int *sih, |
| 1172 |
int dix, int diy, int diw, int dih, |
| 1173 |
int srcW, int dstW, int srcH, int dstH) { |
| 1174 |
double sx, sy, sw, sh; |
| 1175 |
double dx, dy, dw, dh; |
| 1176 |
double wq, hq; |
| 1177 |
|
| 1178 |
dx = dix; dy = diy; |
| 1179 |
dw = diw; dh = dih; |
| 1180 |
|
| 1181 |
wq = ((double)dstW) / (double) srcW; |
| 1182 |
hq = ((double)dstH) / (double) srcH; |
| 1183 |
|
| 1184 |
sx = dx / wq; |
| 1185 |
sy = dy / hq; |
| 1186 |
sw = dw / wq; |
| 1187 |
sh = dh / hq; |
| 1188 |
|
| 1189 |
*six = sx; |
| 1190 |
*siy = sy; |
| 1191 |
*siw = sw+(sx-(int)sx)+0.5; |
| 1192 |
*sih = sh+(sy-(int)sy)+0.5; |
| 1193 |
} |
| 1194 |
|
| 1195 |
|
| 1196 |
static void ZoomSurfaceSrcCoords(int six, int siy, int siw, int sih, |
| 1197 |
int *dix, int *diy, int *diw, int *dih, |
| 1198 |
Surface * src, Surface * dst) |
| 1199 |
{ |
| 1200 |
int dx, dy, dw, dh; |
| 1201 |
int sx, sy, sw, sh; |
| 1202 |
|
| 1203 |
transformZoomSrc(six, siy, siw, sih, |
| 1204 |
&dx, &dy, &dw, &dh, |
| 1205 |
src->w, dst->w, src->h, dst->h); |
| 1206 |
dx-=2; |
| 1207 |
dy-=2; |
| 1208 |
dw+=4; |
| 1209 |
dh+=4; |
| 1210 |
|
| 1211 |
if (dx < 0) |
| 1212 |
dx = 0; |
| 1213 |
if (dy < 0) |
| 1214 |
dy = 0; |
| 1215 |
if (dx+dw > dst->w) |
| 1216 |
dw = dst->w - dx; |
| 1217 |
if (dy+dh > dst->h) |
| 1218 |
dh = dst->h - dy; |
| 1219 |
|
| 1220 |
transformZoomDst(&sx, &sy, &sw, &sh, |
| 1221 |
dx, dy, dw, dh, |
| 1222 |
src->w, dst->w, src->h, dst->h); |
| 1223 |
|
| 1224 |
if (sx+sw > src->w) |
| 1225 |
sw = src->w - sx; |
| 1226 |
if (sy+sh > src->h) |
| 1227 |
sh = src->h - sy; |
| 1228 |
|
| 1229 |
ZoomSurfaceCoords32(sx, sy, sw, sh, dx, dy, src, dst); |
| 1230 |
|
| 1231 |
*dix = dx; |
| 1232 |
*diy = dy; |
| 1233 |
*diw = dw; |
| 1234 |
*dih = dh; |
| 1235 |
} |
| 1236 |
|
| 1237 |
static void ZoomSurfaceCoords32(int sx, int sy, int sw, int sh, |
| 1238 |
int dx, int dy, |
| 1239 |
Surface * src, Surface * dst) |
| 1240 |
{ |
| 1241 |
Surface s2; |
| 1242 |
|
| 1243 |
s2 = *src; |
| 1244 |
s2.pixels = ((char*)s2.pixels) + (sx * s2.BytesPerPixel) + (sy * src->pitch); |
| 1245 |
s2.w = sw; |
| 1246 |
s2.h = sh; |
| 1247 |
sge_transform(&s2, dst, |
| 1248 |
(float)dst->w/(float)src->w, (float)dst->h/(float)src->h, |
| 1249 |
dx, dy); |
| 1250 |
} |
| 1251 |
|
| 1252 |
|
| 1253 |
#define sge_clip_xmin(pnt) 0 |
| 1254 |
#define sge_clip_xmax(pnt) pnt->w |
| 1255 |
#define sge_clip_ymin(pnt) 0 |
| 1256 |
#define sge_clip_ymax(pnt) pnt->h |
| 1257 |
|
| 1258 |
/*================================================================================== |
| 1259 |
// Helper function to sge_transform() |
| 1260 |
// Returns the bounding box |
| 1261 |
//================================================================================== |
| 1262 |
*/ |
| 1263 |
static void _calcRect(Surface *src, Surface *dst, float xscale, float yscale, |
| 1264 |
Uint16 qx, Uint16 qy, |
| 1265 |
Sint16 *xmin, Sint16 *ymin, Sint16 *xmax, Sint16 *ymax) |
| 1266 |
{ |
| 1267 |
Sint16 x, y, rx, ry; |
| 1268 |
int i; |
| 1269 |
|
| 1270 |
/* Clip to src surface */ |
| 1271 |
Sint16 sxmin = sge_clip_xmin(src); |
| 1272 |
Sint16 sxmax = sge_clip_xmax(src); |
| 1273 |
Sint16 symin = sge_clip_ymin(src); |
| 1274 |
Sint16 symax = sge_clip_ymax(src); |
| 1275 |
Sint16 sx[5]; |
| 1276 |
Sint16 sy[4]; |
| 1277 |
|
| 1278 |
/* We don't really need fixed-point here |
| 1279 |
* but why not? */ |
| 1280 |
Sint32 ictx = (Sint32) (xscale * 8192.0); |
| 1281 |
Sint32 icty = (Sint32) (yscale * 8192.0); |
| 1282 |
|
| 1283 |
sx[0] = sxmin; |
| 1284 |
sx[1] = sxmax; |
| 1285 |
sx[2] = sxmin; |
| 1286 |
sx[3] = sxmax; |
| 1287 |
sy[0] = symin; |
| 1288 |
sy[1] = symax; |
| 1289 |
sy[2] = symax; |
| 1290 |
sy[3] = symin; |
| 1291 |
|
| 1292 |
/* Calculate the four corner points */ |
| 1293 |
for(i=0; i<4; i++){ |
| 1294 |
rx = sx[i]; |
| 1295 |
ry = sy[i]; |
| 1296 |
|
| 1297 |
x = (Sint16)(((ictx*rx) >> 13) + qx); |
| 1298 |
y = (Sint16)(((icty*ry) >> 13) + qy); |
| 1299 |
|
| 1300 |
|
| 1301 |
if(i==0){ |
| 1302 |
*xmax = *xmin = x; |
| 1303 |
*ymax = *ymin = y; |
| 1304 |
}else{ |
| 1305 |
if(x>*xmax) |
| 1306 |
*xmax=x; |
| 1307 |
else if(x<*xmin) |
| 1308 |
*xmin=x; |
| 1309 |
|
| 1310 |
if(y>*ymax) |
| 1311 |
*ymax=y; |
| 1312 |
else if(y<*ymin) |
| 1313 |
*ymin=y; |
| 1314 |
} |
| 1315 |
} |
| 1316 |
|
| 1317 |
/* Better safe than sorry...*/ |
| 1318 |
*xmin -= 1; |
| 1319 |
*ymin -= 1; |
| 1320 |
*xmax += 1; |
| 1321 |
*ymax += 1; |
| 1322 |
|
| 1323 |
/* Clip to dst surface */ |
| 1324 |
if( !dst ) |
| 1325 |
return; |
| 1326 |
if( *xmin < sge_clip_xmin(dst) ) |
| 1327 |
*xmin = sge_clip_xmin(dst); |
| 1328 |
if( *xmax > sge_clip_xmax(dst) ) |
| 1329 |
*xmax = sge_clip_xmax(dst); |
| 1330 |
if( *ymin < sge_clip_ymin(dst) ) |
| 1331 |
*ymin = sge_clip_ymin(dst); |
| 1332 |
if( *ymax > sge_clip_ymax(dst) ) |
| 1333 |
*ymax = sge_clip_ymax(dst); |
| 1334 |
} |
| 1335 |
|
| 1336 |
|
| 1337 |
/*================================================================================== |
| 1338 |
** Scale by scale and place at position (qx,qy). |
| 1339 |
** |
| 1340 |
** |
| 1341 |
** Developed with the help from Terry Hancock (hancock@earthlink.net) |
| 1342 |
** |
| 1343 |
**==================================================================================*/ |
| 1344 |
/* First we need some macros to handle different bpp |
| 1345 |
* I'm sorry about this... |
| 1346 |
*/ |
| 1347 |
#define TRANSFORM(UintXX, DIV) \ |
| 1348 |
Sint32 src_pitch=src->pitch/DIV; \ |
| 1349 |
Sint32 dst_pitch=dst->pitch/DIV; \ |
| 1350 |
UintXX *src_row = (UintXX *)src->pixels; \ |
| 1351 |
UintXX *dst_row; \ |
| 1352 |
\ |
| 1353 |
for (y=ymin; y<ymax; y++){ \ |
| 1354 |
dy = y - qy; \ |
| 1355 |
\ |
| 1356 |
sx = (Sint32)ctdx; /* Compute source anchor points */ \ |
| 1357 |
sy = (Sint32)(cty*dy); \ |
| 1358 |
\ |
| 1359 |
/* Calculate pointer to dst surface */ \ |
| 1360 |
dst_row = (UintXX *)dst->pixels + y*dst_pitch; \ |
| 1361 |
\ |
| 1362 |
for (x=xmin; x<xmax; x++){ \ |
| 1363 |
rx=(Sint16)(sx >> 13); /* Convert from fixed-point */ \ |
| 1364 |
ry=(Sint16)(sy >> 13); \ |
| 1365 |
\ |
| 1366 |
/* Make sure the source pixel is actually in the source image. */ \ |
| 1367 |
if( (rx>=sxmin) && (rx<sxmax) && (ry>=symin) && (ry<symax) ) \ |
| 1368 |
*(dst_row + x) = *(src_row + ry*src_pitch + rx); \ |
| 1369 |
\ |
| 1370 |
sx += ctx; /* Incremental transformations */ \ |
| 1371 |
} \ |
| 1372 |
} |
| 1373 |
|
| 1374 |
|
| 1375 |
/* Interpolated transform */ |
| 1376 |
#define TRANSFORM_AA(UintXX, DIV) \ |
| 1377 |
Sint32 src_pitch=src->pitch/DIV; \ |
| 1378 |
Sint32 dst_pitch=dst->pitch/DIV; \ |
| 1379 |
UintXX *src_row = (UintXX *)src->pixels; \ |
| 1380 |
UintXX *dst_row; \ |
| 1381 |
UintXX c1, c2, c3, c4;\ |
| 1382 |
Uint32 R, G, B, A=0; \ |
| 1383 |
UintXX Rmask = image->red_mask;\ |
| 1384 |
UintXX Gmask = image->green_mask;\ |
| 1385 |
UintXX Bmask = image->blue_mask;\ |
| 1386 |
UintXX Amask = 0;\ |
| 1387 |
Uint32 wx, wy;\ |
| 1388 |
Uint32 p1, p2, p3, p4;\ |
| 1389 |
\ |
| 1390 |
/* |
| 1391 |
* Interpolation: |
| 1392 |
* We calculate the distances from our point to the four nearest pixels, d1..d4. |
| 1393 |
* d(a,b) = sqrt(a�+b�) ~= 0.707(a+b) (Pythagoras (Taylor) expanded around (0.5;0.5)) |
| 1394 |
* |
| 1395 |
* 1 wx 2 |
| 1396 |
* *-|-* (+ = our point at (x,y)) |
| 1397 |
* | | | (* = the four nearest pixels) |
| 1398 |
* wy --+ | wx = float(x) - int(x) |
| 1399 |
* | | wy = float(y) - int(y) |
| 1400 |
* *---* |
| 1401 |
* 3 4 |
| 1402 |
* d1 = d(wx,wy) d2 = d(1-wx,wy) d3 = d(wx,1-wy) d4 = d(1-wx,1-wy) |
| 1403 |
* We now want to weight each pixels importance - it's vicinity to our point: |
| 1404 |
* w1=d4 w2=d3 w3=d2 w4=d1 (Yes it works... just think a bit about it) |
| 1405 |
* |
| 1406 |
* If the pixels have the colors c1..c4 then our point should have the color |
| 1407 |
* c = (w1*c1 + w2*c2 + w3*c3 + w4*c4)/(w1+w2+w3+w4) (the weighted average) |
| 1408 |
* but w1+w2+w3+w4 = 4*0.707 so we might as well write it as |
| 1409 |
* c = p1*c1 + p2*c2 + p3*c3 + p4*c4 where p1..p4 = (w1..w4)/(4*0.707) |
| 1410 |
* |
| 1411 |
* But p1..p4 are fixed point so we can just divide the fixed point constant! |
| 1412 |
* 8192/(4*0.71) = 2897 and we can skip 0.71 too (the division will cancel it everywhere) |
| 1413 |
* 8192/4 = 2048 |
| 1414 |
* |
| 1415 |
* 020102: I changed the fixed-point representation for the variables in the weighted average |
| 1416 |
* to 24.7 to avoid problems with 32bit colors. Everything else is still 18.13. This |
| 1417 |
* does however not solve the problem with 32bit RGBA colors... |
| 1418 |
*/\ |
| 1419 |
\ |
| 1420 |
Sint32 one = 2048>>6; /* 1 in Fixed-point */ \ |
| 1421 |
Sint32 two = 2*2048>>6; /* 2 in Fixed-point */ \ |
| 1422 |
\ |
| 1423 |
for (y=ymin; y<ymax; y++){ \ |
| 1424 |
dy = y - qy; \ |
| 1425 |
\ |
| 1426 |
sx = (Sint32)(ctdx); /* Compute source anchor points */ \ |
| 1427 |
sy = (Sint32)(cty*dy); \ |
| 1428 |
\ |
| 1429 |
/* Calculate pointer to dst surface */ \ |
| 1430 |
dst_row = (UintXX *)dst->pixels + y*dst_pitch; \ |
| 1431 |
\ |
| 1432 |
for (x=xmin; x<xmax; x++){ \ |
| 1433 |
rx=(Sint16)(sx >> 13); /* Convert from fixed-point */ \ |
| 1434 |
ry=(Sint16)(sy >> 13); \ |
| 1435 |
\ |
| 1436 |
/* Make sure the source pixel is actually in the source image. */ \ |
| 1437 |
if( (rx>=sxmin) && (rx+1<sxmax) && (ry>=symin) && (ry+1<symax) ){ \ |
| 1438 |
wx = (sx & 0x00001FFF) >>8; /* (float(x) - int(x)) / 4 */ \ |
| 1439 |
wy = (sy & 0x00001FFF) >>8;\ |
| 1440 |
\ |
| 1441 |
p4 = wx+wy;\ |
| 1442 |
p3 = one-wx+wy;\ |
| 1443 |
p2 = wx+one-wy;\ |
| 1444 |
p1 = two-wx-wy;\ |
| 1445 |
\ |
| 1446 |
c1 = *(src_row + ry*src_pitch + rx);\ |
| 1447 |
c2 = *(src_row + ry*src_pitch + rx+1);\ |
| 1448 |
c3 = *(src_row + (ry+1)*src_pitch + rx);\ |
| 1449 |
c4 = *(src_row + (ry+1)*src_pitch + rx+1);\ |
| 1450 |
\ |
| 1451 |
/* Calculate the average */\ |
| 1452 |
R = ((p1*(c1 & Rmask) + p2*(c2 & Rmask) + p3*(c3 & Rmask) + p4*(c4 & Rmask))>>7) & Rmask;\ |
| 1453 |
G = ((p1*(c1 & Gmask) + p2*(c2 & Gmask) + p3*(c3 & Gmask) + p4*(c4 & Gmask))>>7) & Gmask;\ |
| 1454 |
B = ((p1*(c1 & Bmask) + p2*(c2 & Bmask) + p3*(c3 & Bmask) + p4*(c4 & Bmask))>>7) & Bmask;\ |
| 1455 |
if(Amask)\ |
| 1456 |
A = ((p1*(c1 & Amask) + p2*(c2 & Amask) + p3*(c3 & Amask) + p4*(c4 & Amask))>>7) & Amask;\ |
| 1457 |
\ |
| 1458 |
*(dst_row + x) = R | G | B | A;\ |
| 1459 |
} \ |
| 1460 |
sx += ctx; /* Incremental transformations */ \ |
| 1461 |
} \ |
| 1462 |
} |
| 1463 |
|
| 1464 |
void sge_transform(Surface *src, Surface *dst, float xscale, float yscale, Uint16 qx, Uint16 qy) |
| 1465 |
{ |
| 1466 |
Sint32 dy, sx, sy; |
| 1467 |
Sint16 x, y, rx, ry; |
| 1468 |
Rect r; |
| 1469 |
|
| 1470 |
Sint32 ctx, cty; |
| 1471 |
Sint16 xmin, xmax, ymin, ymax; |
| 1472 |
Sint16 sxmin, sxmax, symin, symax; |
| 1473 |
Sint32 dx, ctdx; |
| 1474 |
|
| 1475 |
|
| 1476 |
/* Here we use 18.13 fixed point integer math |
| 1477 |
// Sint32 should have 31 usable bits and one for sign |
| 1478 |
// 2^13 = 8192 |
| 1479 |
*/ |
| 1480 |
|
| 1481 |
/* Check scales */ |
| 1482 |
Sint32 maxint = (Sint32)(pow(2, sizeof(Sint32)*8 - 1 - 13)); /* 2^(31-13) */ |
| 1483 |
|
| 1484 |
r.x = r.y = r.w = r.h = 0; |
| 1485 |
|
| 1486 |
if( xscale == 0 || yscale == 0) |
| 1487 |
return; |
| 1488 |
|
| 1489 |
if( 8192.0/xscale > maxint ) |
| 1490 |
xscale = (float)(8192.0/maxint); |
| 1491 |
else if( 8192.0/xscale < -maxint ) |
| 1492 |
xscale = (float)(-8192.0/maxint); |
| 1493 |
|
| 1494 |
if( 8192.0/yscale > maxint ) |
| 1495 |
yscale = (float)(8192.0/maxint); |
| 1496 |
else if( 8192.0/yscale < -maxint ) |
| 1497 |
yscale = (float)(-8192.0/maxint); |
| 1498 |
|
| 1499 |
|
| 1500 |
/* Fixed-point equivalents */ |
| 1501 |
ctx = (Sint32)(8192.0/xscale); |
| 1502 |
cty = (Sint32)(8192.0/yscale); |
| 1503 |
|
| 1504 |
/* Compute a bounding rectangle */ |
| 1505 |
xmin=0; xmax=dst->w; ymin=0; ymax=dst->h; |
| 1506 |
_calcRect(src, dst, xscale, yscale, |
| 1507 |
qx, qy, &xmin, &ymin, &xmax, &ymax); |
| 1508 |
|
| 1509 |
/* Clip to src surface */ |
| 1510 |
sxmin = sge_clip_xmin(src); |
| 1511 |
sxmax = sge_clip_xmax(src); |
| 1512 |
symin = sge_clip_ymin(src); |
| 1513 |
symax = sge_clip_ymax(src); |
| 1514 |
|
| 1515 |
/* Some terms in the transform are constant */ |
| 1516 |
dx = xmin - qx; |
| 1517 |
ctdx = ctx*dx; |
| 1518 |
|
| 1519 |
/* Use the correct bpp */ |
| 1520 |
if( src->BytesPerPixel == dst->BytesPerPixel){ |
| 1521 |
switch( src->BytesPerPixel ){ |
| 1522 |
case 1: { /* Assuming 8-bpp */ |
| 1523 |
TRANSFORM(Uint8, 1) |
| 1524 |
} |
| 1525 |
break; |
| 1526 |
case 2: { /* Probably 15-bpp or 16-bpp */ |
| 1527 |
TRANSFORM_AA(Uint16, 2) |
| 1528 |
} |
| 1529 |
break; |
| 1530 |
case 4: { /* Probably 32-bpp */ |
| 1531 |
TRANSFORM_AA(Uint32, 4) |
| 1532 |
} |
| 1533 |
break; |
| 1534 |
} |
| 1535 |
} |
| 1536 |
} |
| 1537 |
|
| 1538 |
void freeDesktopResources() { |
| 1539 |
Cleanup(); |
| 1540 |
if (image) { |
| 1541 |
XDestroyImage(image); |
| 1542 |
} |
| 1543 |
if (zoomImage) { |
| 1544 |
XDestroyImage(zoomImage); |
| 1545 |
} |
| 1546 |
if (savedArea) |
| 1547 |
free(savedArea); |
| 1548 |
|
| 1549 |
if (gcInited) { |
| 1550 |
XFreeGC(dpy, gc); |
| 1551 |
XFreeGC(dpy, srcGC); |
| 1552 |
XFreeGC(dpy, dstGC); |
| 1553 |
} |
| 1554 |
|
| 1555 |
caughtShmError = False; |
| 1556 |
needShmCleanup = False; |
| 1557 |
caughtZoomShmError = False; |
| 1558 |
needZoomShmCleanup = False; |
| 1559 |
gcInited = False; |
| 1560 |
image = NULL; |
| 1561 |
useShm = True; |
| 1562 |
zoomActive = False; |
| 1563 |
zoomImage = NULL; |
| 1564 |
useZoomShm = True; |
| 1565 |
savedArea = NULL; |
| 1566 |
} |
| 1567 |
|
| 1568 |
|
| 1569 |
/* |
| 1570 |
* ColorRectangle32 |
| 1571 |
* Only used for debugging / visualizing output |
| 1572 |
*/ |
| 1573 |
/* |
| 1574 |
static void |
| 1575 |
ColorRectangle32(XImage *img, CARD32 fg, int x, int y, int width, int height) |
| 1576 |
{ |
| 1577 |
int i, h; |
| 1578 |
int scrWidthInBytes = img->bytes_per_line; |
| 1579 |
char *scr; |
| 1580 |
CARD32 *scr32; |
| 1581 |
|
| 1582 |
if ((!img) || (!img->data)) |
| 1583 |
return; |
| 1584 |
|
| 1585 |
scr = (img->data + y * scrWidthInBytes + x * 4); |
| 1586 |
|
| 1587 |
if (!CheckRectangle(x, y, width, height)) |
| 1588 |
return; |
| 1589 |
|
| 1590 |
for (h = 0; h < height; h++) { |
| 1591 |
scr32 = (CARD32*) scr; |
| 1592 |
for (i = 0; i < width; i++) { |
| 1593 |
CARD32 n = 0; |
| 1594 |
CARD32 p = scr32[i]; |
| 1595 |
if (0xff & fg) |
| 1596 |
n |= ((( 0xff & p)+( 0xff & fg)) >> 2) & 0xff; |
| 1597 |
else |
| 1598 |
n |= (0xff & p); |
| 1599 |
if (0xff00 & fg) |
| 1600 |
n |= ((( 0xff00 & p)+( 0xff00 & fg)) >> 2) & 0xff00; |
| 1601 |
else |
| 1602 |
n |= (0xff00 & p); |
| 1603 |
if (0xff0000 & fg) |
| 1604 |
n |= (((0xff0000 & p)+(0xff0000 & fg)) >> 2) & 0xff0000; |
| 1605 |
else |
| 1606 |
n |= (0xff0000 & p); |
| 1607 |
scr32[i] = n; |
| 1608 |
} |
| 1609 |
scr += scrWidthInBytes; |
| 1610 |
} |
| 1611 |
} |
| 1612 |
*/ |
| 1613 |
|