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
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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
27
* - added Zoom functionality, based on rotation funcs from
28
* SGE by Anders Lindstrļæ½m)
29
* - added support for softcursor encoding
34
* desktop.c - functions to deal with "desktop" window.
40
#include <X11/extensions/XShm.h>
43
#include "vncviewer.h"
45
static XShmSegmentInfo shminfo;
46
static Bool caughtShmError = False;
47
static Bool needShmCleanup = False;
49
static XShmSegmentInfo zoomshminfo;
50
static Bool caughtZoomShmError = False;
51
static Bool needZoomShmCleanup = False;
53
static Bool gcInited = False;
55
GC srcGC, dstGC; /* used for debugging copyrect */
56
Dimension dpyWidth, dpyHeight;
58
static XImage *image = NULL;
61
static Bool zoomActive = False;
62
static int zoomWidth, zoomHeight;
63
static XImage *zoomImage = NULL;
64
static Bool useZoomShm = True;
67
static char *savedArea = NULL;
71
SOFTCURSOR_PART_UNDER,
78
typedef unsigned int Uint32;
79
typedef unsigned short Uint16;
80
typedef unsigned char Uint8;
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);
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);
120
DesktopInit(Window win)
124
image = CreateShmImage();
128
image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL,
129
si.framebufferWidth, si.framebufferHeight,
132
image->data = calloc(image->bytes_per_line * image->height, 1);
134
fprintf(stderr,"malloc failed\n");
139
gc = XCreateGC(dpy,win,0,NULL);
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);
150
* DrawScreenRegionX11Thread
151
* Never call from any other desktop.c function, only for X11 thread
155
DrawScreenRegionX11Thread(Window win, int x, int y, int width, int height) {
164
XShmPutImage(dpy, win, gc, image, x, y, x, y, width, height, False);
166
XPutImage(dpy, win, gc, image, x, y, x, y, width, height);
173
static int CheckRectangle(int x, int y, int width, int height) {
174
if ((x < 0) || (y < 0))
177
if (((x+width) > si.framebufferWidth) || ((y+height) > si.framebufferHeight))
184
void bgr233cpy(CARD8 *dst, CARD8 *src, int len) {
191
for (i = 0; i < len; i++)
192
*(dst++) = (CARD8) BGR233ToPixel[*(src++)];
196
for (i = 0; i < len; i++)
197
*(d16++) = (CARD16) BGR233ToPixel[*(src++)];
201
for (i = 0; i < len; i++)
202
*(d32++) = (CARD32) BGR233ToPixel[*(src++)];
205
fprintf(stderr, "Unsupported softcursor depth %d\n", visbpp);
215
CopyDataToScreen(char *buf, int x, int y, int width, int height)
219
if (!CheckRectangle(x, y, width, height))
223
s = getSoftCursorState(x, y, width, height);
224
if (s == SOFTCURSOR_PART_UNDER)
227
if (!appData.useBGR233)
228
CopyDataToScreenRaw(buf, x, y, width, height);
230
CopyBGR233ToScreen((CARD8 *)buf, x, y, width, height);
232
if (s != SOFTCURSOR_UNAFFECTED)
236
SyncScreenRegion(x, y, width, height);
240
* CopyDataToScreenRaw.
244
CopyDataToScreenRaw(char *buf, int x, int y, int width, int height)
247
int widthInBytes = width * visbpp / 8;
248
int scrWidthInBytes = image->bytes_per_line;
249
char *scr = (image->data + y * scrWidthInBytes
252
for (h = 0; h < height; h++) {
253
memcpy(scr, buf, widthInBytes);
255
scr += scrWidthInBytes;
260
* CopyBGR233ToScreen.
264
CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width, int height)
267
int xoff = 7 - (x & 7);
269
int fbwb = si.framebufferWidth / 8;
270
CARD8 *scr1 = ((CARD8 *)image->data) + y * fbwb + x / 8;
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;
278
/* thanks to Chris Hooper for single bpp support */
281
for (q = 0; q < height; q++) {
284
for (p = 0; p < width; p++) {
285
*scrt = ((*scrt & ~(1 << xcur))
286
| (BGR233ToPixel[*(buf++)] << xcur));
298
for (q = 0; q < height; q++) {
299
for (p = 0; p < width; p++) {
300
*(scr8++) = BGR233ToPixel[*(buf++)];
302
scr8 += si.framebufferWidth - width;
307
for (q = 0; q < height; q++) {
308
for (p = 0; p < width; p++) {
309
*(scr16++) = BGR233ToPixel[*(buf++)];
311
scr16 += si.framebufferWidth - width;
316
for (q = 0; q < height; q++) {
317
for (p = 0; p < width; p++) {
318
*(scr32++) = BGR233ToPixel[*(buf++)];
320
scr32 += si.framebufferWidth - width;
331
FillRectangle8(CARD8 fg, int x, int y, int width, int height)
335
if (!CheckRectangle(x, y, width, height))
338
s = getSoftCursorState(x, y, width, height);
339
if (s == SOFTCURSOR_PART_UNDER)
342
if (!appData.useBGR233) {
344
int widthInBytes = width * visbpp / 8;
345
int scrWidthInBytes = image->bytes_per_line;
347
char *scr = (image->data + y * scrWidthInBytes
350
for (h = 0; h < height; h++) {
351
memset(scr, fg, widthInBytes);
352
scr += scrWidthInBytes;
355
FillRectangleBGR233(fg, x, y, width, height);
358
if (s != SOFTCURSOR_UNAFFECTED)
363
* FillRectangleBGR233.
367
FillRectangleBGR233(CARD8 fg, int x, int y, int width, int height)
370
int xoff = 7 - (x & 7);
372
int fbwb = si.framebufferWidth / 8;
373
CARD8 *scr1 = ((CARD8 *)image->data) + y * fbwb + x / 8;
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;
379
unsigned long fg233 = BGR233ToPixel[fg];
383
/* thanks to Chris Hooper for single bpp support */
386
for (q = 0; q < height; q++) {
389
for (p = 0; p < width; p++) {
390
*scrt = ((*scrt & ~(1 << xcur))
403
for (q = 0; q < height; q++) {
404
for (p = 0; p < width; p++) {
407
scr8 += si.framebufferWidth - width;
412
for (q = 0; q < height; q++) {
413
for (p = 0; p < width; p++) {
416
scr16 += si.framebufferWidth - width;
421
for (q = 0; q < height; q++) {
422
for (p = 0; p < width; p++) {
425
scr32 += si.framebufferWidth - width;
436
FillRectangle16(CARD16 fg, int x, int y, int width, int height)
439
int scrWidthInBytes = image->bytes_per_line;
441
char *scr = (image->data + y * scrWidthInBytes
446
if (!CheckRectangle(x, y, width, height))
449
s = getSoftCursorState(x, y, width, height);
450
if (s == SOFTCURSOR_PART_UNDER)
453
for (h = 0; h < height; h++) {
454
scr16 = (CARD16*) scr;
455
for (i = 0; i < width; i++)
457
scr += scrWidthInBytes;
460
if (s != SOFTCURSOR_UNAFFECTED)
469
FillRectangle32(CARD32 fg, int x, int y, int width, int height)
472
int scrWidthInBytes = image->bytes_per_line;
475
char *scr = (image->data + y * scrWidthInBytes
479
if (!CheckRectangle(x, y, width, height))
482
s = getSoftCursorState(x, y, width, height);
483
if (s == SOFTCURSOR_PART_UNDER)
486
for (h = 0; h < height; h++) {
487
scr32 = (CARD32*) scr;
488
for (i = 0; i < width; i++)
490
scr += scrWidthInBytes;
493
if (s != SOFTCURSOR_UNAFFECTED)
498
* CopyDataFromScreen.
502
CopyDataFromScreen(char *buf, int x, int y, int width, int height)
504
int widthInBytes = width * visbpp / 8;
505
int scrWidthInBytes = image->bytes_per_line;
506
char *src = (image->data + y * scrWidthInBytes
510
if (!CheckRectangle(x, y, width, height))
513
for (h = 0; h < height; h++) {
514
memcpy(buf, src, widthInBytes);
515
src += scrWidthInBytes;
525
CopyArea(int srcX, int srcY, int width, int height, int x, int y)
527
int widthInBytes = width * visbpp / 8;
528
SoftCursorState sSrc, sDst;
531
sSrc = getSoftCursorState(srcX, srcY, width, height);
532
sDst = getSoftCursorState(x, y, width, height);
533
if ((sSrc != SOFTCURSOR_UNAFFECTED) ||
534
(sDst == SOFTCURSOR_PART_UNDER))
537
if ((srcY+height < y) || (y+height < srcY) ||
538
(srcX+width < x) || (x+width < srcX)) {
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
547
if (!CheckRectangle(srcX, srcY, width, height)) {
551
if (!CheckRectangle(x, y, width, height)) {
556
for (h = 0; h < height; h++) {
557
memcpy(dst, src, widthInBytes);
558
src += scrWidthInBytes;
559
dst += scrWidthInBytes;
563
char *buf = malloc(widthInBytes*height);
566
fprintf(stderr, "Out of memory, CopyArea impossible\n");
569
CopyDataFromScreen(buf, srcX, srcY, width, height);
570
CopyDataToScreenRaw(buf, x, y, width, height);
573
if ((sSrc != SOFTCURSOR_UNAFFECTED) ||
574
(sDst != SOFTCURSOR_UNAFFECTED))
577
SyncScreenRegion(x, y, width, height);
580
void SyncScreenRegion(int x, int y, int width, int height) {
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;
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);
599
dw = width; dh = height;
601
DrawScreenRegion(dx, dy, dw, dh);
604
void SyncScreenRegionX11Thread(int x, int y, int width, int height) {
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;
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);
623
dw = width; dh = height;
625
DrawAnyScreenRegionX11Thread(dx, dy, dw, dh);
629
* ToplevelInitBeforeRealization sets the title, geometry and other resources
630
* on the toplevel window.
636
dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy));
637
dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy));
641
* Cleanup - perform shm cleanup operations prior to exiting.
647
if (useShm || useZoomShm)
654
fprintf(stderr,"ShmCleanup called\n");
655
if (needShmCleanup) {
656
shmdt(shminfo.shmaddr);
657
shmctl(shminfo.shmid, IPC_RMID, 0);
658
needShmCleanup = False;
660
if (needZoomShmCleanup) {
661
shmdt(zoomshminfo.shmaddr);
662
shmctl(zoomshminfo.shmid, IPC_RMID, 0);
663
needZoomShmCleanup = False;
668
ShmCreationXErrorHandler(Display *d, XErrorEvent *e)
670
caughtShmError = True;
678
XErrorHandler oldXErrorHandler;
680
if (!XShmQueryExtension(dpy))
683
_image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo,
684
si.framebufferWidth, si.framebufferHeight);
685
if (!_image) return NULL;
687
shminfo.shmid = shmget(IPC_PRIVATE,
688
_image->bytes_per_line * _image->height,
691
if (shminfo.shmid == -1) {
692
XDestroyImage(_image);
696
shminfo.shmaddr = _image->data = shmat(shminfo.shmid, 0, 0);
698
if (shminfo.shmaddr == (char *)-1) {
699
XDestroyImage(_image);
700
shmctl(shminfo.shmid, IPC_RMID, 0);
704
shminfo.readOnly = True;
706
oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler);
707
XShmAttach(dpy, &shminfo);
709
XSetErrorHandler(oldXErrorHandler);
711
if (caughtShmError) {
712
XDestroyImage(_image);
713
shmdt(shminfo.shmaddr);
714
shmctl(shminfo.shmid, IPC_RMID, 0);
718
needShmCleanup = True;
720
fprintf(stderr,"Using shared memory PutImage\n");
725
void undrawCursor() {
728
if ((imageIndex < 0) || !savedArea)
731
getBoundingRectCursor(cursorX, cursorY, imageIndex,
734
if ((w < 1) || (h < 1))
737
CopyDataToScreenRaw(savedArea, x, y, w, h);
738
discardCursorSavedArea();
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];
749
/* check whether the source image has ended (image broken) */
750
#define CHECK_IMG(x) if (&img[x] > imgEnd) goto imgError
752
/* check whether the end of the framebuffer has been reached (last line) */
753
#define CHECK_END() if ((wl == 0) && (h == 1)) return
755
/* skip x pixels in the source (x must be < pixelsLeft!) */
756
#define SKIP_IMG(x) if ((x > 0) && !processingMask) { \
762
/* skip x pixels in source and destination */
763
#define SKIP_PIXELS(x) { int wl = x; \
764
while (pixelsLeft <= wl) { \
766
SKIP_IMG(pixelsLeft); \
768
pixelsLeft = *(img++); \
770
processingMask = processingMask ? 0 : 1; \
779
x = cursorX - pi->hotX;
780
y = cursorY - pi->hotY;
784
if (!rectsIntersect(x, y, w, h,
785
0, 0, si.framebufferWidth, si.framebufferHeight)) {
786
fprintf(stderr, "intersect abort\n");
790
pw = myFormat.bitsPerPixel / 8;
792
pixelsLeft = *(img++);
794
/* at this point everything is initialized for the macros */
796
/* skip/clip bottom lines */
797
if ((y+h) > si.framebufferHeight)
798
h = si.framebufferHeight - y;
800
/* Skip invisible top lines */
807
/* calculate left/right clipping */
816
if ((x+w) > si.framebufferWidth) {
817
skipRight = (x+w) - si.framebufferWidth;
818
w = si.framebufferWidth - x;
823
fb = (CARD8*) image->data + y * image->bytes_per_line + x * visbpp / 8;
825
/* Paint the thing */
827
SKIP_PIXELS(skipLeft);
832
while (pixelsLeft <= wl) {
834
if ((pixelsLeft > 0) && !processingMask) {
835
int pl = pw * pixelsLeft;
837
if (!appData.useBGR233)
838
memcpy(fbx, img, pl);
840
bgr233cpy(fbx, img, pixelsLeft);
845
fbx += pixelsLeft * visbpp / 8;
846
pixelsLeft = *(img++);
849
processingMask = processingMask ? 0 : 1;
852
if ((wl > 0) && !processingMask) {
855
if (!appData.useBGR233)
856
memcpy(fbx, img, pl);
858
bgr233cpy(fbx, img, wl);
863
SKIP_PIXELS(skipRight);
864
fb += image->bytes_per_line;
870
fprintf(stderr, "Error in softcursor image %d\n", imageIndex);
871
pointerImages[imageIndex].set = 0;
874
static void discardCursorSavedArea() {
880
static void saveCursorSavedArea() {
885
getBoundingRectCursor(cursorX, cursorY, imageIndex,
887
if ((w < 1) || (h < 1))
889
discardCursorSavedArea();
890
savedArea = malloc(h*image->bytes_per_line);
892
fprintf(stderr,"malloc failed, saving cursor not possible\n");
895
CopyDataFromScreen(savedArea, x, y, w, h);
899
saveCursorSavedArea();
903
void getBoundingRectCursor(int cx, int cy, int _imageIndex,
904
int *x, int *y, int *w, int *h) {
907
if ((_imageIndex < 0) || !pointerImages[_imageIndex].set) {
915
nx = cx - pointerImages[_imageIndex].hotX;
916
ny = cy - pointerImages[_imageIndex].hotY;
917
nw = pointerImages[_imageIndex].w;
918
nh = pointerImages[_imageIndex].h;
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)) {
945
static SoftCursorState getSoftCursorState(int x, int y, int w, int h) {
949
return SOFTCURSOR_UNAFFECTED;
951
getBoundingRectCursor(cursorX, cursorY, imageIndex,
954
if ((cw == 0) || (ch == 0))
955
return SOFTCURSOR_UNAFFECTED;
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;
962
return SOFTCURSOR_PART_UNDER;
965
int rectsIntersect(int x, int y, int w, int h,
966
int x2, int y2, int w2, int h2) {
978
int rectContains(int outX, int outY, int outW, int outH,
979
int inX, int inY, int inW, int inH) {
984
if ((inX+inW) > (outX+outW))
986
if ((inY+inH) > (outY+outH))
991
void rectsJoin(int *nx1, int *ny1, int *nw1, int *nh1,
992
int x2, int y2, int w2, int h2) {
1007
if ((x2+w2) > (ox+ow))
1009
if ((y2+h2) > (oy+oh))
1019
CreateShmZoomImage()
1022
XErrorHandler oldXErrorHandler;
1024
if (!XShmQueryExtension(dpy))
1027
_image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &zoomshminfo,
1028
si.framebufferWidth, si.framebufferHeight);
1029
if (!_image) return NULL;
1031
zoomshminfo.shmid = shmget(IPC_PRIVATE,
1032
_image->bytes_per_line * _image->height,
1035
if (zoomshminfo.shmid == -1) {
1036
XDestroyImage(_image);
1040
zoomshminfo.shmaddr = _image->data = shmat(zoomshminfo.shmid, 0, 0);
1042
if (zoomshminfo.shmaddr == (char *)-1) {
1043
XDestroyImage(_image);
1044
shmctl(zoomshminfo.shmid, IPC_RMID, 0);
1048
zoomshminfo.readOnly = True;
1050
oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler);
1051
XShmAttach(dpy, &zoomshminfo);
1053
XSetErrorHandler(oldXErrorHandler);
1055
if (caughtZoomShmError) {
1056
XDestroyImage(_image);
1057
shmdt(zoomshminfo.shmaddr);
1058
shmctl(zoomshminfo.shmid, IPC_RMID, 0);
1062
needZoomShmCleanup = True;
1064
fprintf(stderr,"Using shared memory PutImage\n");
1071
* DrawZoomedScreenRegionX11Thread
1072
* Never call from any other desktop.c function, only for X11 thread
1076
DrawZoomedScreenRegionX11Thread(Window win, int zwidth, int zheight,
1077
int x, int y, int width, int height) {
1081
if (zwidth > si.framebufferWidth)
1082
zwidth = si.framebufferWidth;
1083
if (zheight > si.framebufferHeight)
1084
zheight = si.framebufferHeight;
1091
if ((zoomWidth != zwidth) || (zoomHeight != zheight)) {
1095
zoomHeight = zheight;
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;
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,
1112
XShmPutImage(dpy, win, gc, zoomImage, 0, 0, 0, 0, zwidth, zheight, False);
1114
XPutImage(dpy, win, gc, zoomImage, 0, 0, 0, 0, zwidth, zheight);
1119
XShmPutImage(dpy, win, gc, zoomImage, x, y, x, y, width, height, False);
1121
XPutImage(dpy, win, gc, zoomImage, x, y, x, y, width, height);
1131
zoomImage = CreateShmZoomImage();
1135
zoomImage = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL,
1136
si.framebufferWidth, si.framebufferHeight,
1139
zoomImage->data = calloc(zoomImage->bytes_per_line * zoomImage->height, 1);
1140
if (!zoomImage->data) {
1141
fprintf(stderr,"malloc failed\n");
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;
1157
wq = ((double)dstW) / (double) srcW;
1158
hq = ((double)dstH) / (double) srcH;
1167
*diw = dw+(dx-(int)dx)+0.5;
1168
*dih = dh+(dy-(int)dy)+0.5;
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;
1181
wq = ((double)dstW) / (double) srcW;
1182
hq = ((double)dstH) / (double) srcH;
1191
*siw = sw+(sx-(int)sx)+0.5;
1192
*sih = sh+(sy-(int)sy)+0.5;
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)
1203
transformZoomSrc(six, siy, siw, sih,
1205
src->w, dst->w, src->h, dst->h);
1220
transformZoomDst(&sx, &sy, &sw, &sh,
1222
src->w, dst->w, src->h, dst->h);
1229
ZoomSurfaceCoords32(sx, sy, sw, sh, dx, dy, src, dst);
1237
static void ZoomSurfaceCoords32(int sx, int sy, int sw, int sh,
1239
Surface * src, Surface * dst)
1244
s2.pixels = ((char*)s2.pixels) + (sx * s2.BytesPerPixel) + (sy * src->pitch);
1247
sge_transform(&s2, dst,
1248
(float)dst->w/(float)src->w, (float)dst->h/(float)src->h,
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
1258
/*==================================================================================
1259
// Helper function to sge_transform()
1260
// Returns the bounding box
1261
//==================================================================================
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)
1267
Sint16 x, y, rx, ry;
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);
1278
/* We don't really need fixed-point here
1280
Sint32 ictx = (Sint32) (xscale * 8192.0);
1281
Sint32 icty = (Sint32) (yscale * 8192.0);
1292
/* Calculate the four corner points */
1297
x = (Sint16)(((ictx*rx) >> 13) + qx);
1298
y = (Sint16)(((icty*ry) >> 13) + qy);
1317
/* Better safe than sorry...*/
1323
/* Clip to dst surface */
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);
1337
/*==================================================================================
1338
** Scale by scale and place at position (qx,qy).
1341
** Developed with the help from Terry Hancock (hancock@earthlink.net)
1343
**==================================================================================*/
1344
/* First we need some macros to handle different bpp
1345
* I'm sorry about this...
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; \
1353
for (y=ymin; y<ymax; y++){ \
1356
sx = (Sint32)ctdx; /* Compute source anchor points */ \
1357
sy = (Sint32)(cty*dy); \
1359
/* Calculate pointer to dst surface */ \
1360
dst_row = (UintXX *)dst->pixels + y*dst_pitch; \
1362
for (x=xmin; x<xmax; x++){ \
1363
rx=(Sint16)(sx >> 13); /* Convert from fixed-point */ \
1364
ry=(Sint16)(sy >> 13); \
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); \
1370
sx += ctx; /* Incremental transformations */ \
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; \
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;\
1388
Uint32 p1, p2, p3, p4;\
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))
1396
* *-|-* (+ = our point at (x,y))
1397
* | | | (* = the four nearest pixels)
1398
* wy --+ | wx = float(x) - int(x)
1399
* | | wy = float(y) - int(y)
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)
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)
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)
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...
1420
Sint32 one = 2048>>6; /* 1 in Fixed-point */ \
1421
Sint32 two = 2*2048>>6; /* 2 in Fixed-point */ \
1423
for (y=ymin; y<ymax; y++){ \
1426
sx = (Sint32)(ctdx); /* Compute source anchor points */ \
1427
sy = (Sint32)(cty*dy); \
1429
/* Calculate pointer to dst surface */ \
1430
dst_row = (UintXX *)dst->pixels + y*dst_pitch; \
1432
for (x=xmin; x<xmax; x++){ \
1433
rx=(Sint16)(sx >> 13); /* Convert from fixed-point */ \
1434
ry=(Sint16)(sy >> 13); \
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;\
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);\
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;\
1456
A = ((p1*(c1 & Amask) + p2*(c2 & Amask) + p3*(c3 & Amask) + p4*(c4 & Amask))>>7) & Amask;\
1458
*(dst_row + x) = R | G | B | A;\
1460
sx += ctx; /* Incremental transformations */ \
1464
void sge_transform(Surface *src, Surface *dst, float xscale, float yscale, Uint16 qx, Uint16 qy)
1467
Sint16 x, y, rx, ry;
1471
Sint16 xmin, xmax, ymin, ymax;
1472
Sint16 sxmin, sxmax, symin, symax;
1476
/* Here we use 18.13 fixed point integer math
1477
// Sint32 should have 31 usable bits and one for sign
1482
Sint32 maxint = (Sint32)(pow(2, sizeof(Sint32)*8 - 1 - 13)); /* 2^(31-13) */
1484
r.x = r.y = r.w = r.h = 0;
1486
if( xscale == 0 || yscale == 0)
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);
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);
1500
/* Fixed-point equivalents */
1501
ctx = (Sint32)(8192.0/xscale);
1502
cty = (Sint32)(8192.0/yscale);
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);
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);
1515
/* Some terms in the transform are constant */
1519
/* Use the correct bpp */
1520
if( src->BytesPerPixel == dst->BytesPerPixel){
1521
switch( src->BytesPerPixel ){
1522
case 1: { /* Assuming 8-bpp */
1526
case 2: { /* Probably 15-bpp or 16-bpp */
1527
TRANSFORM_AA(Uint16, 2)
1530
case 4: { /* Probably 32-bpp */
1531
TRANSFORM_AA(Uint32, 4)
1538
void freeDesktopResources() {
1541
XDestroyImage(image);
1544
XDestroyImage(zoomImage);
1551
XFreeGC(dpy, srcGC);
1552
XFreeGC(dpy, dstGC);
1555
caughtShmError = False;
1556
needShmCleanup = False;
1557
caughtZoomShmError = False;
1558
needZoomShmCleanup = False;
1571
* Only used for debugging / visualizing output
1575
ColorRectangle32(XImage *img, CARD32 fg, int x, int y, int width, int height)
1578
int scrWidthInBytes = img->bytes_per_line;
1582
if ((!img) || (!img->data))
1585
scr = (img->data + y * scrWidthInBytes + x * 4);
1587
if (!CheckRectangle(x, y, width, height))
1590
for (h = 0; h < height; h++) {
1591
scr32 = (CARD32*) scr;
1592
for (i = 0; i < width; i++) {
1594
CARD32 p = scr32[i];
1596
n |= ((( 0xff & p)+( 0xff & fg)) >> 2) & 0xff;
1600
n |= ((( 0xff00 & p)+( 0xff00 & fg)) >> 2) & 0xff00;
1604
n |= (((0xff0000 & p)+(0xff0000 & fg)) >> 2) & 0xff0000;
1606
n |= (0xff0000 & p);
1609
scr += scrWidthInBytes;