~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to master/icv/src/desktop.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: james.westby@ubuntu.com-20080617134654-2y5m7ki93r5c1ysf
Tags: upstream-1.0.9~rc3
ImportĀ upstreamĀ versionĀ 1.0.9~rc3

Show diffs side-by-side

added added

removed removed

Lines of Context:
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
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