Added directory 'util' for accessibility-related
[platform/core/uifw/at-spi2-atk.git] / util / mag_image.c
1 #include "mag_image.h"
2
3
4 static int get_num(char* msg);
5 static void get_coord(char* msg,point *p);
6 static void get_rect(char* msg, point *p1, point *p2);
7 static void compute_center_coord(point p1, point p2, point *center);
8 static xlib_colormap * xlib_get_colormap (Colormap id, Visual *visual, MagnifierData *data);
9 static guint32 mask_table[] = {
10         0x00000000, 0x00000001, 0x00000003, 0x00000007,
11         0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
12         0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
13         0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
14         0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
15         0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
16         0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
17         0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
18         0xffffffff
19 };
20
21 void parse_message(char *msg, MagnifierData *data){
22
23   int type;
24   point roi_pos, roi_size;
25   point mag_pos, mag_size;
26   
27   printf("%s\n",msg);
28   if(msg[0] != '~'){
29     fprintf(stderr,"corrupted message, discarding\n");
30     return;
31   }
32   type = atoi((char*)&msg[1]);
33   switch (type){
34         case FACTOR :
35             old_factor = data->factor;
36             data->factor = get_num(msg);
37             printf("FACTOR = %d\n",data->factor);
38             break;
39         case CONTRAST :
40             data->contrast = get_num(msg);
41             printf("CONTRAST = %d\n",data->contrast);
42             break;
43         case FOLLOW_MOUSE :
44             data->follow_mouse = get_num(msg);
45             printf("FOLLOW_MOUSE = %d\n",data->follow_mouse);
46             break;
47         case COLOR_INVERTED :
48             data->color_inverted = get_num(msg);
49             printf("COLOR_INVERTED = %d\n",data->color_inverted);
50             break;
51         case GOTO :
52             get_coord(msg, &data->center);
53             printf("GOTO = (%d,%d)\n", data->center.x, data->center.y);
54             break;
55         case SET_ROI:
56             get_rect (msg, &roi_pos, &roi_size);
57             printf("ROI = (%d,%d; %d,%d)\n", roi_pos.x, roi_pos.y, roi_size.x, roi_size.y);
58             compute_center_coord (roi_pos, roi_size, &data->center);
59             break;
60         case SET_EXTENTS:
61             get_rect (msg, &mag_pos, &mag_size);
62             printf("EXTENTS = (%d,%d; %d,%d)\n", mag_pos.x, mag_pos.y, mag_size.x, mag_size.y);
63             data->mag_width = mag_size.x;
64             data->mag_height = mag_size.y;
65             gdk_window_move_resize (data->output_window->window, mag_pos.x,
66                                     mag_pos.y,
67                                     data->mag_width, data->mag_height);
68             break;
69         case STOP :
70             printf("STOP\n");
71             gtk_main_quit();
72             break;
73         default:
74             break;
75   }
76 }
77
78
79 static int get_num(char* msg){
80  int type,num;
81  sscanf(msg,"~%d:%d:",&type,&num);
82  return num;
83 }
84
85 static void get_coord(char* msg,point *p){
86  int type;
87  sscanf(msg,"~%d:%d,%d:",&type,&p->x,&p->y);
88 }
89
90 static void get_rect(char* msg, point *p1, point *p2){
91  int type;
92  sscanf(msg,"~%d:%d,%d;%d,%d:",&type, &p1->x, &p1->y, &p2->x, &p2->y);
93 }
94
95 static void compute_center_coord (point pos, point size, point *center) {
96   center->x = pos.x + (size.x/2);
97   center->y = pos.y + (size.y/2);
98 }
99
100 int display_image(gpointer data)
101 {
102   MagnifierData *mag_data = (MagnifierData *)data;
103   update_image(mag_data);
104   gdk_pixbuf_scale(image,
105                    scaled_image,
106                    0,
107                    0,
108                    DisplayWidth (mag_data->target_display,screen_num),
109                    DisplayHeight(mag_data->target_display,screen_num),
110                    0,
111                    0,
112                    mag_data->factor,
113                    mag_data->factor,
114                    GDK_INTERP_NEAREST);
115   
116   gdk_pixbuf_render_to_drawable (scaled_image,
117                         drawing_area->window,
118                         drawing_area->style->fg_gc[GTK_STATE_NORMAL],
119                         0,0,0,0,DisplayWidth (mag_data->target_display,screen_num),
120                         DisplayHeight(mag_data->target_display,screen_num),
121                         GDK_RGB_DITHER_NORMAL,0,0);
122   return TRUE;
123 }
124
125 void update_image(MagnifierData *mag_data)
126 {
127  int x, y, total_width, total_height;
128   
129  if(mag_data->follow_mouse){
130     Window root_return, child_return;
131     int win_x_return,win_y_return;
132     unsigned int mask_return;
133     XQueryPointer(mag_data->source_display,image_root_window,
134                   &root_return,&child_return,
135                   &mag_data->center.x,&mag_data->center.y,
136                   &win_x_return,&win_y_return,&mask_return);
137   }
138
139   total_width = DisplayWidth (mag_data->source_display,screen_num);
140   total_height = DisplayHeight(mag_data->source_display,screen_num);
141
142   x = mag_data->center.x - mag_data->mag_width/mag_data->factor/2;
143   y = mag_data->center.y - mag_data->mag_height/mag_data->factor/2;
144
145   if(mag_data->center.x < mag_data->mag_width/mag_data->factor/2)
146     x = 0;
147   if(mag_data->center.x > (total_width - mag_data->mag_width/mag_data->factor/2))
148     x = total_width - mag_data->mag_width/mag_data->factor;
149   if(mag_data->center.y < mag_data->mag_height/mag_data->factor/2)
150     y = 0;
151   if(mag_data->center.y > (total_height - mag_data->mag_height/mag_data->factor/2))
152     y = total_height - mag_data->mag_height/mag_data->factor;
153   if(x < 0)
154     x = 0;
155   if(y < 0)
156     y = 0;
157 /*
158   printf("p = (%d,%d), x,y = (%d,%d), h,w = (%d,%d), ht,wt = (%d,%d)\n",
159                                         mag_data->center.x,
160                                         mag_data->center.y,
161                                         x,y,
162                                         mag_data->mag_height,mag_data->mag_width,
163                                         total_height,
164                                         total_width);
165 */
166   if(mag_data->factor != old_factor){
167     g_object_unref((GObject *)image);
168     image = gdk_pixbuf_new (GDK_COLORSPACE_RGB,FALSE, 8,
169                                 DisplayWidth (mag_data->target_display,screen_num)/mag_data->factor,
170                                 DisplayHeight(mag_data->target_display,screen_num)/mag_data->factor);
171     /* yes, use target display above, since the size of the area grabbed depends on the target */
172     old_factor = mag_data->factor;
173   }
174   get_root_image(image_root_window,
175                  image,
176                  x,
177                  y,
178                  mag_data);
179 }
180 void expose_event(GtkWidget * w, GdkEventExpose *event, gpointer data){
181
182 }
183
184
185
186
187 /* Image grabbing and convertion routines from gdk-pixbuf-xlib */
188 /*
189   convert 1 bits-pixel data
190   no alpha
191 */
192 static void
193 rgb1 (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
194 {
195         int xx, yy;
196         int width, height;
197         int bpl;
198         guint8 *s;
199         register guint8 data;
200         guint8 *o;
201         guint8 *srow = image->data, *orow = pixels;
202
203         /* convert upto 8 pixels/time */
204         /* its probably not worth trying to make this run very fast, who uses
205            1 bit displays anymore? */
206         width = image->width;
207         height = image->height;
208         bpl = image->bytes_per_line;
209
210         for (yy = 0; yy < height; yy++) {
211                 s = srow;
212                 o = orow;
213
214                 for (xx = 0; xx < width; xx ++) {
215                         data = srow[xx >> 3] >> (7 - (xx & 7)) & 1;
216                         *o++ = colormap->colors[data].red;
217                         *o++ = colormap->colors[data].green;
218                         *o++ = colormap->colors[data].blue;
219                 }
220                 srow += bpl;
221                 orow += rowstride;
222         }
223 }
224
225 /*
226   convert 1 bits/pixel data
227   with alpha
228 */
229 static void
230 rgb1a (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
231 {
232         int xx, yy;
233         int width, height;
234         int bpl;
235         guint8 *s;
236         register guint8 data;
237         guint8 *o;
238         guint8 *srow = image->data, *orow = pixels;
239         guint32 remap[2];
240
241         /* convert upto 8 pixels/time */
242         /* its probably not worth trying to make this run very fast, who uses
243            1 bit displays anymore? */
244         width = image->width;
245         height = image->height;
246         bpl = image->bytes_per_line;
247
248         for (xx = 0; xx < 2; xx++) {
249 #ifdef LITTLE
250                 remap[xx] = 0xff000000
251                         | colormap->colors[xx].blue << 16
252                         | colormap->colors[xx].green << 8
253                         | colormap->colors[xx].red;
254 #else
255                 remap[xx] = 0xff
256                         | colormap->colors[xx].red << 24
257                         | colormap->colors[xx].green << 16
258                         | colormap->colors[xx].blue << 8;
259 #endif
260         }
261
262         for (yy = 0; yy < height; yy++) {
263                 s = srow;
264                 o = orow;
265
266                 for (xx = 0; xx < width; xx ++) {
267                         data = srow[xx >> 3] >> (7 - (xx & 7)) & 1;
268                         *o++ = remap[data];
269                 }
270                 srow += bpl;
271                 orow += rowstride;
272         }
273 }
274
275 /*
276   convert 8 bits/pixel data
277   no alpha
278 */
279 static void
280 rgb8 (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
281 {
282         int xx, yy;
283         int width, height;
284         int bpl;
285         guint32 mask;
286         register guint32 data;
287         guint8 *srow = image->data, *orow = pixels;
288         register guint8 *s;
289         register guint8 *o;
290
291         width = image->width;
292         height = image->height;
293         bpl = image->bytes_per_line;
294
295         mask = mask_table[image->depth];
296
297         for (yy = 0; yy < height; yy++) {
298                 s = srow;
299                 o = orow;
300                 for (xx = 0; xx < width; xx++) {
301                         data = *s++ & mask;
302                         *o++ = colormap->colors[data].red;
303                         *o++ = colormap->colors[data].green;
304                         *o++ = colormap->colors[data].blue;
305                 }
306                 srow += bpl;
307                 orow += rowstride;
308         }
309 }
310
311 /*
312   convert 8 bits/pixel data
313   with alpha
314 */
315 static void
316 rgb8a (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
317 {
318         int xx, yy;
319         int width, height;
320         int bpl;
321         guint32 mask;
322         register guint32 data;
323         guint32 remap[256];
324         register guint8 *s;     /* read 2 pixels at once */
325         register guint32 *o;
326         guint8 *srow = image->data, *orow = pixels;
327
328         width = image->width;
329         height = image->height;
330         bpl = image->bytes_per_line;
331
332         mask = mask_table[image->depth];
333
334         for (xx = 0; xx < colormap->size; xx++) {
335 #ifdef LITTLE
336                 remap[xx] = 0xff000000
337                         | colormap->colors[xx].blue << 16
338                         | colormap->colors[xx].green << 8
339                         | colormap->colors[xx].red;
340 #else
341                 remap[xx] = 0xff
342                         | colormap->colors[xx].red << 24
343                         | colormap->colors[xx].green << 16
344                         | colormap->colors[xx].blue << 8;
345 #endif
346         }
347
348         for (yy = 0; yy < height; yy++) {
349                 s = srow;
350                 o = (guint32 *) orow;
351                 for (xx = 0; xx < width; xx ++) {
352                         data = *s++ & mask;
353                         *o++ = remap[data];
354                 }
355                 srow += bpl;
356                 orow += rowstride;
357         }
358 }
359
360 /*
361   convert 16 bits/pixel data
362   no alpha
363   data in lsb format
364 */
365 static void
366 rgb565lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
367 {
368         int xx, yy;
369         int width, height;
370         int bpl;
371
372 #ifdef LITTLE
373         register guint32 *s;    /* read 2 pixels at once */
374 #else
375         register guint8 *s;     /* read 2 pixels at once */
376 #endif
377         register guint16 *o;
378         guint8 *srow = image->data, *orow = pixels;
379
380         width = image->width;
381         height = image->height;
382         bpl = image->bytes_per_line;
383
384         for (yy = 0; yy < height; yy++) {
385 #ifdef LITTLE
386                 s = (guint32 *) srow;
387 #else
388                 s = srow;
389 #endif
390                 o = (guint16 *) orow;
391                 for (xx = 1; xx < width; xx += 2) {
392                         register guint32 data;
393 #ifdef LITTLE
394                         data = *s++;
395                         *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
396                                 | (data & 0x7e0) << 5 | (data & 0x600) >> 1;
397                         *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
398                                 | (data & 0xf8000000) >> 16 | (data & 0xe0000000) >> 21;
399                         *o++ = (data & 0x7e00000) >> 19 | (data & 0x6000000) >> 25
400                                 | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
401 #else
402                         /* swap endianness first */
403                         data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
404                         s += 4;
405                         *o++ = (data & 0xf800) | (data & 0xe000) >> 5
406                                 | (data & 0x7e0) >> 3 | (data & 0x600) >> 9;
407                         *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
408                                 | (data & 0xf8000000) >> 24 | (data & 0xe0000000) >> 29;
409                         *o++ = (data & 0x7e00000) >> 11 | (data & 0x6000000) >> 17
410                                 | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
411 #endif
412                 }
413                 /* check for last remaining pixel */
414                 if (width & 1) {
415                         register guint16 data;
416 #ifdef LITTLE
417                         data = *((short *) s);
418 #else
419                         data = *((short *) s);
420                         data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
421 #endif
422                         ((char *) o)[0] = ((data >> 8) & 0xf8) | ((data >> 13) & 0x7);
423                         ((char *) o)[1] = ((data >> 3) & 0xfc) | ((data >> 9) & 0x3);
424                         ((char *) o)[2] = ((data << 3) & 0xf8) | ((data >> 2) & 0x7);
425                 }
426                 srow += bpl;
427                 orow += rowstride;
428         }
429 }
430
431 /*
432   convert 16 bits/pixel data
433   no alpha
434   data in msb format
435 */
436 static void
437 rgb565msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
438 {
439         int xx, yy;
440         int width, height;
441         int bpl;
442
443 #ifdef LITTLE
444         register guint8 *s;     /* need to swap data order */
445 #else
446         register guint32 *s;    /* read 2 pixels at once */
447 #endif
448         register guint16 *o;
449         guint8 *srow = image->data, *orow = pixels;
450
451         width = image->width;
452         height = image->height;
453         bpl = image->bytes_per_line;
454
455         for (yy = 0; yy < height; yy++) {
456 #ifdef LITTLE
457                 s = srow;
458 #else
459                 s = (guint32 *) srow;
460 #endif
461                 o = (guint16 *) orow;
462                 for (xx = 1; xx < width; xx += 2) {
463                         register guint32 data;
464 #ifdef LITTLE
465                         /* swap endianness first */
466                         data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
467                         s += 4;
468                         *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
469                                 | (data & 0x7e0) << 5 | (data & 0x600) >> 1;
470                         *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
471                                 | (data & 0xf8000000) >> 16 | (data & 0xe0000000) >> 21;
472                         *o++ = (data & 0x7e00000) >> 19 | (data & 0x6000000) >> 25
473                                 | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
474 #else
475                         data = *s++;
476                         *o++ = (data & 0xf800) | (data & 0xe000) >> 5
477                                 | (data & 0x7e0) >> 3 | (data & 0x600) >> 9;
478                         *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
479                                 | (data & 0xf8000000) >> 24 | (data & 0xe0000000) >> 29;
480                         *o++ = (data & 0x7e00000) >> 11 | (data & 0x6000000) >> 17
481                                 | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
482 #endif
483                 }
484                 /* check for last remaining pixel */
485                 if (width & 1) {
486                         register guint16 data;
487 #ifdef LITTLE
488                         data = *((short *) s);
489                         data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
490 #else
491                         data = *((short *) s);
492 #endif
493                         ((char *) o)[0] = ((data >> 8) & 0xf8) | ((data >> 13) & 0x7);
494                         ((char *) o)[1] = ((data >> 3) & 0xfc) | ((data >> 9) & 0x3);
495                         ((char *) o)[2] = ((data << 3) & 0xf8) | ((data >> 2) & 0x7);
496                 }
497                 srow += bpl;
498                 orow += rowstride;
499         }
500 }
501
502 /*
503   convert 16 bits/pixel data
504   with alpha
505   data in lsb format
506 */
507 static void
508 rgb565alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
509 {
510         int xx, yy;
511         int width, height;
512         int bpl;
513
514 #ifdef LITTLE
515         register guint16 *s;    /* read 1 pixels at once */
516 #else
517         register guint8 *s;
518 #endif
519         register guint32 *o;
520
521         guint8 *srow = image->data, *orow = pixels;
522
523         width = image->width;
524         height = image->height;
525         bpl = image->bytes_per_line;
526
527         for (yy = 0; yy < height; yy++) {
528 #ifdef LITTLE
529                 s = (guint16 *) srow;
530 #else
531                 s = (guint8 *) srow;
532 #endif
533                 o = (guint32 *) orow;
534                 for (xx = 0; xx < width; xx ++) {
535                         register guint32 data;
536                         /*  rrrrrggg gggbbbbb -> rrrrrRRR ggggggGG bbbbbBBB aaaaaaaa */
537                         /*  little endian: aaaaaaaa bbbbbBBB ggggggGG rrrrrRRR */
538 #ifdef LITTLE
539                         data = *s++;
540                         *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
541                                 | (data & 0x7e0) << 5 | (data & 0x600) >> 1
542                                 | (data & 0x1f) << 19 | (data & 0x1c) << 14
543                                 | 0xff000000;
544 #else
545                         /* swap endianness first */
546                         data = s[0] | s[1] << 8;
547                         s += 2;
548                         *o++ = (data & 0xf800) << 16 | (data & 0xe000) << 11
549                                 | (data & 0x7e0) << 13 | (data & 0x600) << 7
550                                 | (data & 0x1f) << 11 | (data & 0x1c) << 6
551                                 | 0xff;
552 #endif
553                 }
554                 srow += bpl;
555                 orow += rowstride;
556         }
557 }
558
559 /*
560   convert 16 bits/pixel data
561   with alpha
562   data in msb format
563 */
564 static void
565 rgb565amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
566 {
567         int xx, yy;
568         int width, height;
569         int bpl;
570
571 #ifdef LITTLE
572         register guint8 *s;
573 #else
574         register guint16 *s;    /* read 1 pixels at once */
575 #endif
576         register guint32 *o;
577
578         guint8 *srow = image->data, *orow = pixels;
579
580         width = image->width;
581         height = image->height;
582         bpl = image->bytes_per_line;
583
584         for (yy = 0; yy < height; yy++) {
585                 s = srow;
586                 o = (guint32 *) orow;
587                 for (xx = 0; xx < width; xx ++) {
588                         register guint32 data;
589                         /*  rrrrrggg gggbbbbb -> rrrrrRRR gggggg00 bbbbbBBB aaaaaaaa */
590                         /*  little endian: aaaaaaaa bbbbbBBB gggggg00 rrrrrRRR */
591 #ifdef LITTLE
592                         /* swap endianness first */
593                         data = s[0] | s[1] << 8;
594                         s += 2;
595                         *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13
596                                 | (data & 0x7e0) << 5 | (data & 0x600) >> 1
597                                 | (data & 0x1f) << 19 | (data & 0x1c) << 14
598                                 | 0xff000000;
599 #else
600                         data = *s++;
601                         *o++ = (data & 0xf800) << 16 | (data & 0xe000) << 11
602                                 | (data & 0x7e0) << 13 | (data & 0x600) << 7
603                                 | (data & 0x1f) << 11 | (data & 0x1c) << 6
604                                 | 0xff;
605 #endif
606                 }
607                 srow += bpl;
608                 orow += rowstride;
609         }
610 }
611
612 /*
613   convert 15 bits/pixel data
614   no alpha
615   data in lsb format
616 */
617 static void
618 rgb555lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
619 {
620         int xx, yy;
621         int width, height;
622         int bpl;
623
624 #ifdef LITTLE
625         register guint32 *s;    /* read 2 pixels at once */
626 #else
627         register guint8 *s;     /* read 2 pixels at once */
628 #endif
629         register guint16 *o;
630         guint8 *srow = image->data, *orow = pixels;
631
632         width = image->width;
633         height = image->height;
634         bpl = image->bytes_per_line;
635
636         for (yy = 0; yy < height; yy++) {
637 #ifdef LITTLE
638                 s = (guint32 *) srow;
639 #else
640                 s = srow;
641 #endif
642                 o = (guint16 *) orow;
643                 for (xx = 1; xx < width; xx += 2) {
644                         register guint32 data;
645 #ifdef LITTLE
646                         data = *s++;
647                         *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
648                                 | (data & 0x3e0) << 6 | (data & 0x380) << 1;
649                         *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
650                                 | (data & 0x7c000000) >> 15 | (data & 0x70000000) >> 20;
651                         *o++ = (data & 0x3e00000) >> 18 | (data & 0x3800000) >> 23
652                                 | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
653 #else
654                         /* swap endianness first */
655                         data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
656                         s += 4;
657                         *o++ = (data & 0x7c00) << 1 | (data & 0x7000) >> 4
658                                 | (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
659                         *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
660                                 | (data & 0x7c000000) >> 23 | (data & 0x70000000) >> 28;
661                         *o++ = (data & 0x3e00000) >> 10 | (data & 0x3800000) >> 15
662                                 | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
663 #endif
664                 }
665                 /* check for last remaining pixel */
666                 if (width & 1) {
667                         register guint16 data;
668 #ifdef LITTLE
669                         data = *((short *) s);
670 #else
671                         data = *((short *) s);
672                         data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
673 #endif
674                         ((char *) o)[0] = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12;
675                         ((char *) o)[1] = (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
676                         ((char *) o)[2] = (data & 0x1f) << 3 | (data & 0x1c) >> 2;
677                 }
678                 srow += bpl;
679                 orow += rowstride;
680         }
681 }
682
683 /*
684   convert 15 bits/pixel data
685   no alpha
686   data in msb format
687 */
688 static void
689 rgb555msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
690 {
691         int xx, yy;
692         int width, height;
693         int bpl;
694
695 #ifdef LITTLE
696         register guint8 *s;     /* read 2 pixels at once */
697 #else
698         register guint32 *s;    /* read 2 pixels at once */
699 #endif
700         register guint16 *o;
701         guint8 *srow = image->data, *orow = pixels;
702
703         width = image->width;
704         height = image->height;
705         bpl = image->bytes_per_line;
706
707         for (yy = 0; yy < height; yy++) {
708                 s = srow;
709                 o = (guint16 *) orow;
710                 for (xx = 1; xx < width; xx += 2) {
711                         register guint32 data;
712 #ifdef LITTLE
713                         /* swap endianness first */
714                         data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
715                         s += 4;
716                         *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
717                                 | (data & 0x3e0) << 6 | (data & 0x380) << 1;
718                         *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2
719                                 | (data & 0x7c000000) >> 15 | (data & 0x70000000) >> 20;
720                         *o++ = (data & 0x3e00000) >> 18 | (data & 0x3800000) >> 23
721                                 | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10;
722 #else
723                         data = *s++;
724                         *o++ = (data & 0x7c00) << 1 | (data & 0x7000) >> 4
725                                 | (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
726                         *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6
727                                 | (data & 0x7c000000) >> 23 | (data & 0x70000000) >> 28;
728                         *o++ = (data & 0x3e00000) >> 10 | (data & 0x3800000) >> 15
729                                 | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18;
730 #endif
731                 }
732                 /* check for last remaining pixel */
733                 if (width & 1) {
734                         register guint16 data;
735 #ifdef LITTLE
736                         data = *((short *) s);
737                         data = ((data >> 8) & 0xff) | ((data & 0xff) << 8);
738 #else
739                         data = *((short *) s);
740 #endif
741                         ((char *) o)[0] = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12;
742                         ((char *) o)[1] = (data & 0x3e0) >> 2 | (data & 0x380) >> 7;
743                         ((char *) o)[2] = (data & 0x1f) << 3 | (data & 0x1c) >> 2;
744                 }
745                 srow += bpl;
746                 orow += rowstride;
747         }
748 }
749
750 /*
751   convert 15 bits/pixel data
752   with alpha
753   data in lsb format
754 */
755 static void
756 rgb555alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
757 {
758         int xx, yy;
759         int width, height;
760         int bpl;
761
762 #ifdef LITTLE
763         register guint16 *s;    /* read 1 pixels at once */
764 #else
765         register guint8 *s;
766 #endif
767         register guint32 *o;
768
769         guint8 *srow = image->data, *orow = pixels;
770
771         width = image->width;
772         height = image->height;
773         bpl = image->bytes_per_line;
774
775         for (yy = 0; yy < height; yy++) {
776 #ifdef LITTLE
777                 s = (guint16 *) srow;
778 #else
779                 s = srow;
780 #endif
781                 o = (guint32 *) orow;
782                 for (xx = 0; xx < width; xx++) {
783                         register guint32 data;
784                         /*  rrrrrggg gggbbbbb -> rrrrrRRR gggggGGG bbbbbBBB aaaaaaaa */
785                         /*  little endian: aaaaaaaa bbbbbBBB gggggGGG rrrrrRRR */
786 #ifdef LITTLE
787                         data = *s++;
788                         *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
789                                 | (data & 0x3e0) << 6 | (data & 0x380) << 1
790                                 | (data & 0x1f) << 19 | (data & 0x1c) << 14
791                                 | 0xff000000;
792 #else
793                         /* swap endianness first */
794                         data = s[0] | s[1] << 8;
795                         s += 2;
796                         *o++ = (data & 0x7c00) << 17 | (data & 0x7000) << 12
797                                 | (data & 0x3e0) << 14 | (data & 0x380) << 9
798                                 | (data & 0x1f) << 11 | (data & 0x1c) << 6
799                                 | 0xff;
800 #endif
801                 }
802                 srow += bpl;
803                 orow += rowstride;
804         }
805 }
806
807 /*
808   convert 15 bits/pixel data
809   with alpha
810   data in msb format
811 */
812 static void
813 rgb555amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
814 {
815         int xx, yy;
816         int width, height;
817         int bpl;
818
819 #ifdef LITTLE
820         register guint16 *s;    /* read 1 pixels at once */
821 #else
822         register guint8 *s;
823 #endif
824         register guint32 *o;
825
826         guint8 *srow = image->data, *orow = pixels;
827
828         width = image->width;
829         height = image->height;
830         bpl = image->bytes_per_line;
831
832         for (yy = 0; yy < height; yy++) {
833 #ifdef LITTLE
834                 s = (guint16 *) srow;
835 #else
836                 s = srow;
837 #endif
838                 o = (guint32 *) orow;
839                 for (xx = 0; xx < width; xx++) {
840                         register guint32 data;
841                         /*  rrrrrggg gggbbbbb -> rrrrrRRR gggggGGG bbbbbBBB aaaaaaaa */
842                         /*  little endian: aaaaaaaa bbbbbBBB gggggGGG rrrrrRRR */
843 #ifdef LITTLE
844                         /* swap endianness first */
845                         data = s[0] | s[1] << 8;
846                         s += 2;
847                         *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12
848                                 | (data & 0x3e0) << 6 | (data & 0x380) << 1
849                                 | (data & 0x1f) << 19 | (data & 0x1c) << 14
850                                 | 0xff000000;
851 #else
852                         data = *s++;
853                         *o++ = (data & 0x7c00) << 17 | (data & 0x7000) << 12
854                                 | (data & 0x3e0) << 14 | (data & 0x380) << 9
855                                 | (data & 0x1f) << 11 | (data & 0x1c) << 6
856                                 | 0xff;
857 #endif
858                 }
859                 srow += bpl;
860                 orow += rowstride;
861         }
862 }
863
864
865 static void
866 rgb888alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
867 {
868         int xx, yy;
869         int width, height;
870         int bpl;
871
872         guint8 *s;      /* for byte order swapping */
873         guint8 *o;
874         guint8 *srow = image->data, *orow = pixels;
875
876         width = image->width;
877         height = image->height;
878         bpl = image->bytes_per_line;
879
880         /* lsb data */
881         for (yy = 0; yy < height; yy++) {
882                 s = srow;
883                 o = orow;
884                 for (xx = 0; xx < width; xx++) {
885                         *o++ = s[2];
886                         *o++ = s[1];
887                         *o++ = s[0];
888                         *o++ = 0xff;
889                         s += 4;
890                 }
891                 srow += bpl;
892                 orow += rowstride;
893         }
894 }
895
896 static void
897 rgb888lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
898 {
899         int xx, yy;
900         int width, height;
901         int bpl;
902
903         guint8 *srow = image->data, *orow = pixels;
904         guint8 *o, *s;
905
906         width = image->width;
907         height = image->height;
908         bpl = image->bytes_per_line;
909
910
911         for (yy = 0; yy < height; yy++) {
912                 s = srow;
913                 o = orow;
914                 for (xx = 0; xx < width; xx++) {
915                         *o++ = s[2];
916                         *o++ = s[1];
917                         *o++ = s[0];
918                         s += 4;
919                 }
920                 srow += bpl;
921                 orow += rowstride;
922         }
923 }
924
925 static void
926 rgb888amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
927 {
928         int xx, yy;
929         int width, height;
930         int bpl;
931
932         guint8 *srow = image->data, *orow = pixels;
933 #ifdef LITTLE
934         guint32 *o;
935         guint32 *s;
936 #else
937         guint8 *s;      /* for byte order swapping */
938         guint8 *o;
939 #endif
940
941
942         width = image->width;
943         height = image->height;
944         bpl = image->bytes_per_line;
945
946         /* msb data */
947         for (yy = 0; yy < height; yy++) {
948 #ifdef LITTLE
949                 s = (guint32 *) srow;
950                 o = (guint32 *) orow;
951 #else
952                 s = srow;
953                 o = orow;
954 #endif
955                 for (xx = 0; xx < width; xx++) {
956 #ifdef LITTLE
957                         *o++ = s[1];
958                         *o++ = s[2];
959                         *o++ = s[3];
960                         *o++ = 0xff;
961                         s += 4;
962 #else
963                         *o++ = (*s << 8) | 0xff; /* untested */
964                         s++;
965 #endif
966                 }
967                 srow += bpl;
968                 orow += rowstride;
969         }
970 }
971
972 static void
973 rgb888msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap)
974 {
975         int xx, yy;
976         int width, height;
977         int bpl;
978
979         guint8 *srow = image->data, *orow = pixels;
980         guint8 *s;
981         guint8 *o;
982
983
984         width = image->width;
985         height = image->height;
986         bpl = image->bytes_per_line;
987
988         for (yy = 0; yy < height; yy++) {
989                 s = srow;
990                 o = orow;
991                 for (xx = 0; xx < width; xx++) {
992                         *o++ = s[1];
993                         *o++ = s[2];
994                         *o++ = s[3];
995                         s += 4;
996                 }
997                 srow += bpl;
998                 orow += rowstride;
999         }
1000 }
1001 static void
1002 visual_decompose_mask (gulong  mask,
1003                        gint   *shift,
1004                        gint   *prec)
1005 {
1006         *shift = 0;
1007         *prec = 0;
1008
1009         while (!(mask & 0x1)) {
1010                 (*shift)++;
1011                 mask >>= 1;
1012         }
1013
1014         while (mask & 0x1) {
1015                 (*prec)++;
1016                 mask >>= 1;
1017         }
1018 }
1019
1020
1021 /*
1022   This should work correctly with any display/any endianness, but will probably
1023   run quite slow
1024 */
1025 static void
1026 convert_real_slow (XImage *image, guchar *pixels, int rowstride, xlib_colormap *cmap, int alpha)
1027 {
1028         int xx, yy;
1029         int width, height;
1030         int bpl;
1031         guint8 *srow = image->data, *orow = pixels;
1032         guint8 *s;
1033         guint8 *o;
1034         guint32 pixel;
1035         Visual *v;
1036         guint8 component;
1037         int i;
1038         int red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec;
1039
1040         width = image->width;
1041         height = image->height;
1042         bpl = image->bytes_per_line;
1043         v = cmap->visual;
1044
1045         visual_decompose_mask (v->red_mask, &red_shift, &red_prec);
1046         visual_decompose_mask (v->green_mask, &green_shift, &green_prec);
1047         visual_decompose_mask (v->blue_mask, &blue_shift, &blue_prec);
1048
1049         for (yy = 0; yy < height; yy++) {
1050                 s = srow;
1051                 o = orow;
1052                 for (xx = 0; xx < width; xx++) {
1053                         pixel = XGetPixel (image, xx, yy);
1054                         switch (v->class) {
1055                                 /* I assume this is right for static & greyscale's too? */
1056                         case StaticGray:
1057                         case GrayScale:
1058                         case StaticColor:
1059                         case PseudoColor:
1060                                 *o++ = cmap->colors[pixel].red;
1061                                 *o++ = cmap->colors[pixel].green;
1062                                 *o++ = cmap->colors[pixel].blue;
1063                                 break;
1064                         case TrueColor:
1065                                 /* This is odd because it must sometimes shift left (otherwise
1066                                    I'd just shift >> (*_shift - 8 + *_prec + <0-7>). This logic
1067                                    should work for all bit sizes/shifts/etc. */
1068                                 component = 0;
1069                                 for (i = 24; i < 32; i += red_prec)
1070                                         component |= ((pixel & v->red_mask) << (32 - red_shift - red_prec)) >> i;
1071                                 *o++ = component;
1072                                 component = 0;
1073                                 for (i = 24; i < 32; i += green_prec)
1074                                         component |= ((pixel & v->green_mask) << (32 - green_shift - green_prec)) >> i;
1075                                 *o++ = component;
1076                                 component = 0;
1077                                 for (i = 24; i < 32; i += blue_prec)
1078                                         component |= ((pixel & v->blue_mask) << (32 - blue_shift - blue_prec)) >> i;
1079                                 *o++ = component;
1080                                 break;
1081                         case DirectColor:
1082                                 *o++ = cmap->colors[((pixel & v->red_mask) << (32 - red_shift - red_prec)) >> 24].red;
1083                                 *o++ = cmap->colors[((pixel & v->green_mask) << (32 - green_shift - green_prec)) >> 24].green;
1084                                 *o++ = cmap->colors[((pixel & v->blue_mask) << (32 - blue_shift - blue_prec)) >> 24].blue;
1085                                 break;
1086                         }
1087                         if (alpha)
1088                                 *o++ = 0xff;
1089                 }
1090                 srow += bpl;
1091                 orow += rowstride;
1092         }
1093 }
1094
1095 static xlib_colormap *
1096 xlib_get_colormap (Colormap id, Visual *visual, MagnifierData *mag_data)
1097 {
1098         int i;
1099         xlib_colormap *xc = g_new (xlib_colormap, 1);
1100
1101         xc->size = visual->map_entries;
1102         xc->colors = g_new (XColor, xc->size);
1103         xc->visual = visual;
1104         xc->colormap = id;
1105
1106         for (i = 0; i < xc->size; i++) {
1107                 xc->colors[i].pixel = i;
1108                 xc->colors[i].flags = DoRed | DoGreen | DoBlue;
1109         }
1110
1111         XQueryColors (mag_data->source_display, xc->colormap, xc->colors, xc->size);
1112
1113         return xc;
1114 }
1115
1116 typedef void (* cfunc) (XImage *image, guchar *pixels, int rowstride, xlib_colormap *cmap);
1117 static cfunc convert_map[] = {
1118         rgb1,rgb1,rgb1a,rgb1a,
1119         rgb8,rgb8,rgb8a,rgb8a,
1120         rgb555lsb,rgb555msb,rgb555alsb,rgb555amsb,
1121         rgb565lsb,rgb565msb,rgb565alsb,rgb565amsb,
1122         rgb888lsb,rgb888msb,rgb888alsb,rgb888amsb
1123 };
1124
1125 static void
1126 rgbconvert (XImage *image, guchar *pixels, int rowstride, int alpha, xlib_colormap *cmap)
1127 {
1128         int index = (image->byte_order == MSBFirst) | (alpha != 0) << 1;
1129         int bank=5;             /* default fallback converter */
1130         Visual *v = cmap->visual;
1131
1132         switch (v->class) {
1133                                 /* I assume this is right for static & greyscale's too? */
1134         case StaticGray:
1135         case GrayScale:
1136         case StaticColor:
1137         case PseudoColor:
1138                 switch (image->bits_per_pixel) {
1139                 case 1:
1140                         bank = 0;
1141                         break;
1142                 case 8:
1143                         bank = 1;
1144                         break;
1145                 }
1146                 break;
1147         case TrueColor:
1148                 switch (image->depth) {
1149                 case 15:
1150                         if (v->red_mask == 0x7c00 && v->green_mask == 0x3e0 && v->blue_mask == 0x1f
1151                             && image->bits_per_pixel == 16)
1152                                 bank = 2;
1153                         break;
1154                 case 16:
1155                         if (v->red_mask == 0xf800 && v->green_mask == 0x7e0 && v->blue_mask == 0x1f
1156                             && image->bits_per_pixel == 16)
1157                                 bank = 3;
1158                         break;
1159                 case 24:
1160                 case 32:
1161                         if (v->red_mask == 0xff0000 && v->green_mask == 0xff00 && v->blue_mask == 0xff
1162                             && image->bits_per_pixel == 32)
1163                                 bank = 4;
1164                         break;
1165                 }
1166                 break;
1167         case DirectColor:
1168                 /* always use the slow version */
1169                 break;
1170         }
1171
1172         if (bank==5) {
1173                 convert_real_slow(image, pixels, rowstride, cmap, alpha);
1174         } else {
1175                 index |= bank << 2;
1176                 (* convert_map[index]) (image, pixels, rowstride, cmap);
1177         }
1178 }
1179
1180     
1181
1182 void get_root_image(Window src,GdkPixbuf *dest, int src_x, int src_y, MagnifierData *mag_data)  {
1183         XImage *image;
1184         int width = mag_data->mag_width/mag_data->factor;
1185         int height = mag_data->mag_height/mag_data->factor;
1186
1187         /* Get Image in ZPixmap format (packed bits). */
1188         image = XGetImage (mag_data->source_display, src, src_x, src_y,
1189                            width, height, AllPlanes, ZPixmap);
1190         g_assert(image != NULL);
1191
1192         if(x_cmap == NULL){
1193             XWindowAttributes wa;
1194             XGetWindowAttributes (mag_data->source_display, src, &wa);
1195             x_cmap = xlib_get_colormap (wa.colormap, wa.visual, mag_data);                        
1196         }
1197         /* we offset into the image data based on the position we are retrieving from */
1198         rgbconvert (image, gdk_pixbuf_get_pixels(dest),
1199                     gdk_pixbuf_get_rowstride(dest),
1200                     gdk_pixbuf_get_has_alpha(dest),
1201                     x_cmap);
1202         XDestroyImage (image);
1203 }
1204
1205