1 /* $XConsortium: multiVis.c /main/4 1996/10/14 15:04:08 swick $ */
2 /** ------------------------------------------------------------------------
3 This file contains functions to create a list of regions which
4 tile a specified window. Each region contains all visible
5 portions of the window which are drawn with the same visual.
6 If the window consists of subwindows of two different visual types,
7 there will be two regions in the list. The list can be traversed
8 to correctly pull an image of the window using XGetImage or the
9 Image Library.
10
11 Copyright (c) 1994 Hewlett-Packard Co.
12 Copyright (c) 1996 X Consortium
13
14 Permission is hereby granted, free of charge, to any person obtaining
15 a copy of this software and associated documentation files (the
16 "Software"), to deal in the Software without restriction, including
17 without limitation the rights to use, copy, modify, merge, publish,
18 distribute, sublicense, and sell copies of the Software, and to
19 permit persons to whom the Software is furnished to do so, subject to
20 the following conditions:
21
22 The above copyright notice and this permission notice shall be included
23 in all copies or substantial portions of the Software.
24
25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
28 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
29 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
31 OTHER DEALINGS IN THE SOFTWARE.
32
33 Except as contained in this notice, the name of the X Consortium shall
34 not be used in advertising or otherwise to promote the sale, use or
35 other dealings in this Software without prior written authorization
36 from the X Consortium.
37
38 ------------------------------------------------------------------------ **/
39 #include <stdlib.h>
40 #include <X11/Xlib.h>
41 #include <X11/Xutil.h>
42 #include <X11/X.h>
43 #include <stdio.h>
44 #include "list.h"
45 #include "wsutils.h"
46 #include "multiVis.h"
47 static char *vis_class_str[] = { "StaticGray" , "GrayScale" , "StaticColor",
48 "PseudoColor","TrueColor","DirectColor" } ;
49 /* These structures are copied from X11/region.h. For some reason
50 * they're invisible from the outside.
51 */
52 typedef struct {
53 short x1, x2, y1, y2;
54 } myBox, myBOX, myBoxRec, *myBoxPtr;
55
56 typedef struct my_XRegion {
57 long size;
58 long numRects;
59 myBOX *rects;
60 myBOX extents;
61 } myREGION;
62
63 /* Items in long list of windows that have some part in the grabbed area */
64 typedef struct {
65 Window win;
66 Visual *vis;
67 Colormap cmap;
68 int x_rootrel, y_rootrel; /* root relative location of window */
69 int x_vis, y_vis; /* rt rel x,y of vis part, not parent clipped */
70 int width, height; /* width and height of visible part */
71 int border_width; /* border width of the window */
72 Window parent; /* id of parent (for debugging) */
73 } image_win_type;
74
75 /* Items in short list of regions that tile the grabbed area. May have
76 multiple windows in the region.
77 */
78 typedef struct {
79 Window win; /* lowest window of this visual */
80 Visual *vis;
81 Colormap cmap;
82 int x_rootrel, y_rootrel; /* root relative location of bottom window */
83 int x_vis, y_vis; /* rt rel x,y of vis part, not parent clipped */
84 int width, height; /* w & h of visible rect of bottom window */
85 int border; /* border width of the window */
86 Region visible_region;
87 } image_region_type;
88
89 /** ------------------------------------------------------------------------
90 Returns TRUE if the two structs pointed to have the same "vis" &
91 "cmap" fields and s2 lies completely within s1. s1 and s2 can
92 point to structs of image_win_type or image_region_type.
93 ------------------------------------------------------------------------ **/
94 #define SAME_REGIONS( s1, s2) \
95 ((s1)->vis == (s2)->vis && (s1)->cmap == (s2)->cmap && \
96 (s1)->x_vis <= (s2)->x_vis && \
97 (s1)->y_vis <= (s2)->y_vis && \
98 (s1)->x_vis + (s1)->width >= (s2)->x_vis + (s2)->width && \
99 (s1)->y_vis + (s1)->height >= (s2)->y_vis + (s2)->height)
100
101 #ifndef MIN
102 #define MIN( a, b) ((a) < (b) ? a : b)
103 #define MAX( a, b) ((a) > (b) ? a : b)
104 #endif
105
106 #define RED_SHIFT 16
107 #define GREEN_SHIFT 8
108 #define BLUE_SHIFT 0
109
110 /*
111 extern list_ptr new_list();
112 extern list_ptr dup_list_head();
113 extern void * first_in_list();
114 extern void * next_in_list();
115 extern int add_to_list();
116 extern void zero_list();
117 extern void delete_list();
118 extern void delete_list_destroying();
119 extern unsigned int list_length();
120 */
121
122 /* Prototype Declarations for Static Functions */
123 static int QueryColorMap(
124 #if NeedFunctionPrototypes
125 Display *, Colormap , Visual *,
126 XColor **, int *, int *, int *
127 #endif
128 );
129 static void TransferImage(
130 #if NeedFunctionPrototypes
131 Display *, XImage *,int, int , image_region_type*,
132 XImage *,int ,int
133 #endif
134 );
135 static XImage * ReadRegionsInList(
136 #if NeedFunctionPrototypes
137 Display *, Visual *, int ,int ,int ,
138 int , XRectangle, list_ptr
139 #endif
140 );
141
142 static list_ptr make_region_list(
143 #if NeedFunctionPrototypes
144 Display*, Window, XRectangle*,
145 int*, int, XVisualInfo**, int *
146 #endif
147 );
148
149 static void destroy_region_list(
150 #if NeedFunctionPrototypes
151 list_ptr
152 #endif
153 ) ;
154 static void subtr_rect_from_image_region(
155 #if NeedFunctionPrototypes
156 image_region_type *, int , int , int , int
157 #endif
158 );
159 static void add_rect_to_image_region(
160 #if NeedFunctionPrototypes
161 image_region_type *,
162 int , int , int , int
163 #endif
164 );
165 static int src_in_region_list(
166 #if NeedFunctionPrototypes
167 image_win_type *, list_ptr
168 #endif
169 );
170 static void add_window_to_list(
171 #if NeedFunctionPrototypes
172 list_ptr, Window, int, int ,
173 int , int , int , int, int,
174 Visual*, Colormap, Window
175 #endif
176 );
177 static int src_in_image(
178 #if NeedFunctionPrototypes
179 image_win_type *, int , XVisualInfo**
180 #endif
181 );
182 static int src_in_overlay(
183 #if NeedFunctionPrototypes
184 image_region_type *, int, OverlayInfo *, int*, int*
185 #endif
186 );
187
188 /* End of Prototype Declarations */
189
initFakeVisual(Vis)190 void initFakeVisual(Vis)
191 Visual *Vis ;
192 {
193 Vis->ext_data=NULL;
194 Vis->class = DirectColor ;
195 Vis->red_mask = 0x00FF0000;
196 Vis->green_mask = 0x0000FF00 ;
197 Vis->blue_mask = 0x000000FF ;
198 Vis->map_entries = 256 ;
199 Vis->bits_per_rgb = 8 ;
200 }
201
202 static int
QueryColorMap(disp,src_cmap,src_vis,src_colors,rShift,gShift,bShift)203 QueryColorMap(disp,src_cmap,src_vis,src_colors,rShift,gShift,bShift)
204 Display *disp ;
205 Visual *src_vis ;
206 Colormap src_cmap ;
207 XColor **src_colors ;
208 int *rShift, *gShift, *bShift;
209 {
210 int ncolors,i ;
211 unsigned long redMask, greenMask, blueMask, pixel;
212 int redShift, greenShift, blueShift;
213 XColor *colors ;
214
215 ncolors = src_vis->map_entries ;
216 *src_colors = colors = (XColor *)malloc(ncolors * sizeof(XColor) ) ;
217
218 if(src_vis->class != TrueColor && src_vis->class != DirectColor)
219 {
220 for(i=0 ; i < ncolors ; i++)
221 {
222 colors[i].pixel = i ;
223 colors[i].pad = 0;
224 colors[i].flags = DoRed|DoGreen|DoBlue;
225 }
226 }
227 else /** src is decomposed rgb ***/
228 {
229 /* Get the X colormap */
230 redMask = src_vis->red_mask;
231 greenMask = src_vis->green_mask;
232 blueMask = src_vis->blue_mask;
233 redShift = 0; while (!(redMask&0x1)) {
234 redShift++;
235 redMask = redMask>>1;
236 }
237 greenShift = 0; while (!(greenMask&0x1)) {
238 greenShift++;
239 greenMask = greenMask>>1;
240 }
241 blueShift = 0; while (!(blueMask&0x1)) {
242 blueShift++;
243 blueMask = blueMask>>1;
244 }
245 *rShift = redShift ;
246 *gShift = greenShift ;
247 *bShift = blueShift ;
248 for (i=0; i<ncolors; i++) {
249 if( i <= redMask)colors[i].pixel = (i<<redShift) ;
250 if( i <= greenMask)colors[i].pixel |= (i<<greenShift) ;
251 if( i <= blueMask)colors[i].pixel |= (i<<blueShift) ;
252 /***** example :for gecko's 3-3-2 map, blue index should be <= 3.
253 colors[i].pixel = (i<<redShift)|(i<<greenShift)|(i<<blueShift);
254 *****/
255 colors[i].pad = 0;
256 colors[i].flags = DoRed|DoGreen|DoBlue;
257 }
258 }
259
260
261 XQueryColors(disp, src_cmap, colors, ncolors);
262 return ncolors ;
263 }
264
265 int
GetMultiVisualRegions(disp,srcRootWinid,x,y,width,height,transparentOverlays,numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals,numImageVisuals,pImageVisuals,vis_regions,vis_image_regions,allImage)266 GetMultiVisualRegions(disp,srcRootWinid, x, y, width, height,
267 transparentOverlays,numVisuals, pVisuals,numOverlayVisuals, pOverlayVisuals,
268 numImageVisuals, pImageVisuals,vis_regions,vis_image_regions,allImage)
269 Display *disp;
270 Window srcRootWinid; /* root win on which grab was done */
271 int x; /* root rel UL corner of bounding box of grab */
272 int y;
273 unsigned int width; /* size of bounding box of grab */
274 unsigned int height;
275 int *transparentOverlays ;
276 int *numVisuals;
277 XVisualInfo **pVisuals;
278 int *numOverlayVisuals;
279 OverlayInfo **pOverlayVisuals;
280 int *numImageVisuals;
281 XVisualInfo ***pImageVisuals;
282 list_ptr *vis_regions; /* list of regions to read from */
283 list_ptr *vis_image_regions ;
284 int *allImage ;
285 {
286 int hasNonDefault;
287 XRectangle bbox; /* bounding box of grabbed area */
288
289
290 bbox.x = x; /* init X rect for bounding box */
291 bbox.y = y;
292 bbox.width = width;
293 bbox.height = height;
294
295 GetXVisualInfo(disp,DefaultScreen(disp),
296 transparentOverlays,
297 numVisuals, pVisuals,
298 numOverlayVisuals, pOverlayVisuals,
299 numImageVisuals, pImageVisuals);
300
301 *vis_regions = *vis_image_regions = NULL ;
302 if ((*vis_regions = make_region_list( disp, srcRootWinid, &bbox,
303 &hasNonDefault, *numImageVisuals,
304 *pImageVisuals, allImage)) == NULL)
305 return 0 ;
306
307 if (*transparentOverlays)
308 {
309 *allImage = 1; /* until proven otherwise,
310 this flags that it to be an image only list */
311 *vis_image_regions =
312 make_region_list( disp, srcRootWinid, &bbox, &hasNonDefault,
313 *numImageVisuals, *pImageVisuals, allImage);
314 }
315
316 /* if there is a second region in any of the two lists return 1 **/
317 if ( ( *vis_regions && (*vis_regions)->next && (*vis_regions)->next->next ) ||
318 ( *vis_image_regions && (*vis_image_regions)->next &&
319 (*vis_image_regions)->next->next ) ) return 1 ;
320 else return 0 ;
321
322 }
323
TransferImage(disp,reg_image,srcw,srch,reg,target_image,dst_x,dst_y)324 static void TransferImage(disp,reg_image,srcw,srch,reg,
325 target_image,dst_x,dst_y)
326 Display *disp;
327 XImage *reg_image,*target_image ;
328 image_region_type *reg;
329 int srcw,srch,dst_x , dst_y ;
330 {
331 int *indexMap,ncolors ;
332 int i,j,old_pixel,new_pixel,red_ind,green_ind,blue_ind ;
333 XColor *colors;
334 int rShift,gShift,bShift;
335 int targetBytesPerLine ;
336
337 ncolors = QueryColorMap(disp,reg->cmap,reg->vis,&colors,
338 &rShift,&gShift,&bShift) ;
339
340 targetBytesPerLine = target_image->bytes_per_line;
341
342 switch (reg->vis->class) {
343 case TrueColor :
344 for(i=0 ; i < srch ; i++)
345 {
346 for(j=0 ; j < srcw ; j++)
347 {
348 old_pixel = XGetPixel(reg_image,j,i) ;
349
350 if( reg->vis->map_entries == 16) {
351
352 red_ind = (old_pixel & reg->vis->red_mask) >> rShift ;
353 green_ind = (old_pixel & reg->vis->green_mask) >> gShift ;
354 blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ;
355
356 new_pixel = (
357 ((colors[red_ind].red >> 8) << RED_SHIFT)
358 |((colors[green_ind].green >> 8) << GREEN_SHIFT)
359 |((colors[blue_ind].blue >> 8) << BLUE_SHIFT)
360 );
361 }
362 else
363 new_pixel = old_pixel;
364
365 XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
366
367 }
368 }
369 break;
370 case DirectColor :
371 for(i=0 ; i < srch ; i++)
372 {
373
374 for(j=0 ; j < srcw ; j++)
375 {
376 old_pixel = XGetPixel(reg_image,j,i) ;
377 red_ind = (old_pixel & reg->vis->red_mask) >> rShift ;
378 green_ind = (old_pixel & reg->vis->green_mask) >> gShift ;
379 blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ;
380
381 new_pixel = (
382 ((colors[red_ind].red >> 8) << RED_SHIFT)
383 |((colors[green_ind].green >> 8) << GREEN_SHIFT)
384 |((colors[blue_ind].blue >> 8) << BLUE_SHIFT)
385 );
386 XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
387
388 }
389 }
390 break;
391 default :
392 for(i=0 ; i < srch ; i++)
393 {
394 for(j=0 ; j < srcw ; j++)
395 {
396 old_pixel = XGetPixel(reg_image,j,i) ;
397
398 new_pixel = (
399 ((colors[old_pixel].red >> 8) << RED_SHIFT)
400 |((colors[old_pixel].green >> 8) << GREEN_SHIFT)
401 |((colors[old_pixel].blue >> 8) << BLUE_SHIFT)
402 );
403 XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
404
405 }
406 }
407 break;
408 }
409 }
410
411 static XImage *
ReadRegionsInList(disp,fakeVis,depth,format,width,height,bbox,regions)412 ReadRegionsInList(disp,fakeVis,depth,format,width,height,bbox,regions)
413 Display *disp ;
414 Visual *fakeVis ;
415 int depth , width , height ;
416 int format ;
417 XRectangle bbox; /* bounding box of grabbed area */
418 list_ptr regions;/* list of regions to read from */
419 {
420 image_region_type *reg;
421 int dst_x, dst_y; /* where in pixmap to write (UL) */
422 int diff;
423 int hasNonDefault;
424
425 int allImage = 0;
426 int transparentColor, transparentType;
427 XImage *reg_image,*ximage ;
428 int srcRect_x,srcRect_y,srcRect_width,srcRect_height ;
429 int rem ;
430 int bytes_per_line;
431 int bitmap_unit;
432
433 bitmap_unit = sizeof (long);
434 if (format == ZPixmap)
435 bytes_per_line = width*depth/8;
436 else
437 bytes_per_line = width/8;
438
439
440 /* Find out how many more bytes are required for padding so that
441 ** bytes per scan line will be multiples of bitmap_unit bits */
442 if (format == ZPixmap) {
443 rem = (bytes_per_line*8)%bitmap_unit;
444 if (rem)
445 bytes_per_line += (rem/8 + 1);
446 }
447
448 ximage = XCreateImage(disp,fakeVis,depth,format,0,NULL,width,height,
449 8,0) ;
450 bytes_per_line = ximage->bytes_per_line;
451
452 if (format == ZPixmap)
453 ximage->data = malloc(height*bytes_per_line);
454 else
455 ximage->data = malloc(height*bytes_per_line*depth);
456
457 ximage->bits_per_pixel = depth; /** Valid only if format is ZPixmap ***/
458
459 for (reg = (image_region_type *) first_in_list( regions); reg;
460 reg = (image_region_type *) next_in_list( regions))
461 {
462 int rect;
463 struct my_XRegion *vis_reg;
464 vis_reg = (struct my_XRegion *)(reg->visible_region);
465 for (rect = 0;
466 rect < vis_reg->numRects;
467 rect++)
468 {
469 /** ------------------------------------------------------------------------
470 Intersect bbox with visible part of region giving src rect & output
471 location. Width is the min right side minus the max left side.
472 Similar for height. Offset src rect so x,y are relative to
473 origin of win, not the root-relative visible rect of win.
474 ------------------------------------------------------------------------ **/
475 srcRect_width = MIN( vis_reg->rects[rect].x2, bbox.width + bbox.x) -
476 MAX( vis_reg->rects[rect].x1, bbox.x);
477 srcRect_height = MIN( vis_reg->rects[rect].y2, bbox.height + bbox.y) -
478 MAX( vis_reg->rects[rect].y1, bbox.y);
479 diff = bbox.x - vis_reg->rects[rect].x1;
480 srcRect_x = MAX( 0, diff) + (vis_reg->rects[rect].x1 - reg->x_rootrel - reg->border);
481 dst_x = MAX( 0, -diff) ;
482 diff = bbox.y - vis_reg->rects[rect].y1;
483 srcRect_y = MAX( 0, diff) + (vis_reg->rects[rect].y1 - reg->y_rootrel - reg->border);
484 dst_y = MAX( 0, -diff) ;
485 reg_image = XGetImage(disp,reg->win,srcRect_x,srcRect_y,
486 srcRect_width,srcRect_height,AllPlanes,format) ;
487 TransferImage(disp,reg_image,srcRect_width,
488 srcRect_height,reg,ximage,dst_x,dst_y) ;
489 }
490 }
491 return ximage ;
492 }
493
494
495 /** ------------------------------------------------------------------------
496 ------------------------------------------------------------------------ **/
497
ReadAreaToImage(disp,srcRootWinid,x,y,width,height,numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals,numImageVisuals,pImageVisuals,vis_regions,vis_image_regions,format,allImage)498 XImage *ReadAreaToImage(disp, srcRootWinid, x, y, width, height,
499 numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals,numImageVisuals,
500 pImageVisuals,vis_regions,vis_image_regions,format,allImage)
501 Display *disp;
502 Window srcRootWinid; /* root win on which grab was done */
503 int x; /* root rel UL corner of bounding box of grab */
504 int y;
505 unsigned int width; /* size of bounding box of grab */
506 unsigned int height;
507 /** int transparentOverlays; ***/
508 int numVisuals;
509 XVisualInfo *pVisuals;
510 int numOverlayVisuals;
511 OverlayInfo *pOverlayVisuals;
512 int numImageVisuals;
513 XVisualInfo **pImageVisuals;
514 list_ptr vis_regions; /* list of regions to read from */
515 list_ptr vis_image_regions ;/* list of regions to read from */
516 int format;
517 int allImage ;
518 {
519 image_region_type *reg;
520 XRectangle bbox; /* bounding box of grabbed area */
521 int depth ;
522 XImage *ximage, *ximage_ipm ;
523 Visual fakeVis ;
524 int x1, y1;
525 XImage *image;
526 unsigned char *pmData , *ipmData ;
527 int transparentColor, transparentType;
528 int srcRect_x,srcRect_y,srcRect_width,srcRect_height ;
529 int diff ;
530 int dst_x, dst_y; /* where in pixmap to write (UL) */
531 int pixel;
532
533 bbox.x = x; /* init X rect for bounding box */
534 bbox.y = y;
535 bbox.width = width;
536 bbox.height = height;
537
538
539 initFakeVisual(&fakeVis) ;
540
541 depth = 24 ;
542 ximage = ReadRegionsInList(disp,&fakeVis,depth,format,width,height,
543 bbox,vis_regions) ;
544 pmData = (unsigned char *)ximage -> data ;
545
546 /* if transparency possible do it again, but this time for image planes only */
547 if (vis_image_regions && (vis_image_regions->next) && !allImage)
548 {
549 ximage_ipm = ReadRegionsInList(disp,&fakeVis,depth,format,width,height,
550 bbox,vis_image_regions) ;
551 ipmData = (unsigned char *)ximage_ipm -> data ;
552 }
553 /* Now tranverse the overlay visual windows and test for transparency index. */
554 /* If you find one, subsitute the value from the matching image plane pixmap. */
555
556 for (reg = (image_region_type *) first_in_list( vis_regions); reg;
557 reg = (image_region_type *) next_in_list( vis_regions))
558 {
559
560 if (src_in_overlay( reg, numOverlayVisuals, pOverlayVisuals,
561 &transparentColor, &transparentType))
562 {
563 int test = 0 ;
564 srcRect_width = MIN( reg->width + reg->x_vis, bbox.width + bbox.x)
565 - MAX( reg->x_vis, bbox.x);
566 srcRect_height = MIN( reg->height + reg->y_vis, bbox.height
567 + bbox.y) - MAX( reg->y_vis, bbox.y);
568 diff = bbox.x - reg->x_vis;
569 srcRect_x = MAX( 0, diff) + (reg->x_vis - reg->x_rootrel - reg->border);
570 dst_x = MAX( 0, -diff) ;
571 diff = bbox.y - reg->y_vis;
572 srcRect_y = MAX( 0, diff) + (reg->y_vis - reg->y_rootrel - reg->border);
573 dst_y = MAX( 0, -diff) ;
574 /* let's test some pixels for transparency */
575 image = XGetImage(disp, reg->win, srcRect_x, srcRect_y,
576 srcRect_width, srcRect_height, 0xffffffff, ZPixmap);
577
578 /* let's assume byte per pixel for overlay image for now */
579 if ((image->depth == 8) && (transparentType == TransparentPixel))
580 {
581 unsigned char *pixel_ptr;
582 unsigned char *start_of_line = (unsigned char *) image->data;
583
584 for (y1 = 0; y1 < srcRect_height; y1++) {
585 pixel_ptr = start_of_line;
586 for (x1 = 0; x1 < srcRect_width; x1++)
587 {
588 if (*pixel_ptr++ == transparentColor)
589 {
590 /*
591 *pmData++ = *ipmData++;
592 *pmData++ = *ipmData++;
593 *pmData++ = *ipmData++;
594 */
595 pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
596 XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
597
598 if(!test){
599 test = 1 ;
600 }
601 }
602 /*
603 else {
604 pmData +=3;
605 ipmData +=3;
606 }
607 */
608 }
609 start_of_line += image->bytes_per_line;
610 }
611 } else {
612 if (transparentType == TransparentPixel) {
613 for (y1 = 0; y1 < srcRect_height; y1++) {
614 for (x1 = 0; x1 < srcRect_width; x1++)
615 {
616 int pixel_value = XGetPixel(image, x1, y1);
617 if (pixel_value == transparentColor)
618 {
619 /*
620 *pmData++ = *ipmData++;
621 *pmData++ = *ipmData++;
622 *pmData++ = *ipmData++;
623 */
624 pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
625 XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
626 if(!test){
627 test = 1 ;
628 }
629 }
630 /*
631 else {
632 pmData +=3;
633 ipmData +=3;
634 }
635 */
636 }
637 }
638 } else {
639 for (y1 = 0; y1 < srcRect_height; y1++) {
640 for (x1 = 0; x1 < srcRect_width; x1++)
641 {
642 int pixel_value = XGetPixel(image, x1, y1);
643 if (pixel_value & transparentColor)
644 {
645 /*
646 *pmData++ = *ipmData++;
647 *pmData++ = *ipmData++;
648 *pmData++ = *ipmData++;
649 */
650 pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
651 XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
652 if(!test){
653 test = 1 ;
654 }
655 }
656 /*
657 else {
658 pmData +=3;
659 ipmData +=3;
660 }
661 */
662 }
663 }
664 }
665 }
666 XDestroyImage (image);
667 } /* end of src_in_overlay */
668 } /** end transparency **/
669 destroy_region_list( vis_regions);
670 if (vis_image_regions) destroy_region_list( vis_image_regions );
671 FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals);
672 XSync(disp, 0);
673
674 return ximage;
675 }
676
677 /** ------------------------------------------------------------------------
678 Creates a list of the subwindows of a given window which have a
679 different visual than their parents. The function is recursive.
680 This list is used in make_region_list(), which coalesces the
681 windows with the same visual into a region.
682 image_wins must point to an existing list struct that's already
683 been zeroed (zero_list()).
684 ------------------------------------------------------------------------ **/
make_src_list(disp,image_wins,bbox,curr,x_rootrel,y_rootrel,curr_attrs,pclip)685 static void make_src_list( disp, image_wins, bbox, curr, x_rootrel, y_rootrel,
686 curr_attrs, pclip)
687 Display *disp;
688 list_ptr image_wins;
689 XRectangle *bbox; /* bnding box of area we want */
690 Window curr;
691 int x_rootrel; /* pos of curr WRT root */
692 int y_rootrel;
693 XWindowAttributes *curr_attrs;
694 XRectangle *pclip; /* visible part of curr, not */
695 /* obscurred by ancestors */
696 {
697 XWindowAttributes child_attrs;
698 Window root, parent, *child; /* variables for XQueryTree() */
699 Window *save_child_list; /* variables for XQueryTree() */
700 unsigned int nchild; /* variables for XQueryTree() */
701 XRectangle child_clip; /* vis part of child */
702 int curr_clipX, curr_clipY, curr_clipRt, curr_clipBt;
703
704 /* check that win is mapped & not outside bounding box */
705 if (curr_attrs->map_state == IsViewable &&
706 curr_attrs->class == InputOutput &&
707 !( pclip->x >= (int) (bbox->x + bbox->width) ||
708 pclip->y >= (int) (bbox->y + bbox->height) ||
709 (int) (pclip->x + pclip->width) <= bbox->x ||
710 (int) (pclip->y + pclip->height) <= bbox->y)) {
711
712 XQueryTree( disp, curr, &root, &parent, &child, &nchild );
713 save_child_list = child; /* so we can free list when we're done */
714 add_window_to_list( image_wins, curr, x_rootrel, y_rootrel,
715 pclip->x, pclip->y,
716 pclip->width, pclip->height,
717 curr_attrs->border_width,curr_attrs->visual,
718 curr_attrs->colormap, parent);
719
720
721 /** ------------------------------------------------------------------------
722 set RR coords of right (Rt), left (X), bottom (Bt) and top (Y)
723 of rect we clip all children by. This is our own clip rect (pclip)
724 inflicted on us by our parent plus our own borders. Within the
725 child loop, we figure the clip rect for each child by adding in
726 it's rectangle (not taking into account the child's borders).
727 ------------------------------------------------------------------------ **/
728 curr_clipX = MAX( pclip->x, x_rootrel + (int) curr_attrs->border_width);
729 curr_clipY = MAX( pclip->y, y_rootrel + (int) curr_attrs->border_width);
730 curr_clipRt = MIN( pclip->x + (int) pclip->width,
731 x_rootrel + (int) curr_attrs->width +
732 2 * (int) curr_attrs->border_width);
733 curr_clipBt = MIN( pclip->y + (int) pclip->height,
734 y_rootrel + (int) curr_attrs->height +
735 2 * (int) curr_attrs->border_width);
736
737 while (nchild--) {
738 int new_width, new_height;
739 int child_xrr, child_yrr; /* root relative x & y of child */
740
741 XGetWindowAttributes( disp, *child, &child_attrs);
742
743 /* intersect parent & child clip rects */
744 child_xrr = x_rootrel + child_attrs.x + curr_attrs->border_width;
745 child_clip.x = MAX( curr_clipX, child_xrr);
746 new_width = MIN( curr_clipRt, child_xrr + (int) child_attrs.width
747 + 2 * child_attrs.border_width)
748 - child_clip.x;
749 if (new_width >= 0) {
750 child_clip.width = new_width;
751
752 child_yrr = y_rootrel + child_attrs.y +
753 curr_attrs->border_width;
754 child_clip.y = MAX( curr_clipY, child_yrr);
755 new_height = MIN( curr_clipBt,
756 child_yrr + (int) child_attrs.height +
757 2 * child_attrs.border_width)
758 - child_clip.y;
759 if (new_height >= 0) {
760 child_clip.height = new_height;
761 make_src_list( disp, image_wins, bbox, *child,
762 child_xrr, child_yrr,
763 &child_attrs, &child_clip);
764 }
765 }
766 child++;
767 }
768 XFree( save_child_list);
769 }
770 }
771
772
773 /** ------------------------------------------------------------------------
774 This function creates a list of regions which tile a specified
775 window. Each region contains all visible portions of the window
776 which are drawn with the same visual. For example, if the
777 window consists of subwindows of two different visual types,
778 there will be two regions in the list.
779 Returns a pointer to the list.
780 ------------------------------------------------------------------------ **/
make_region_list(disp,win,bbox,hasNonDefault,numImageVisuals,pImageVisuals,allImage)781 static list_ptr make_region_list( disp, win, bbox, hasNonDefault,
782 numImageVisuals, pImageVisuals, allImage)
783 Display *disp;
784 Window win;
785 XRectangle *bbox;
786 int *hasNonDefault;
787 int numImageVisuals;
788 XVisualInfo **pImageVisuals;
789 int *allImage;
790 {
791 XWindowAttributes win_attrs;
792 list image_wins;
793 list_ptr image_regions;
794 list_ptr srcs_left;
795 image_region_type *new_reg;
796 image_win_type *base_src, *src;
797 Region bbox_region = XCreateRegion();
798 XRectangle clip;
799 int image_only;
800
801 int count=0 ;
802
803 *hasNonDefault = False;
804 XUnionRectWithRegion( bbox, bbox_region, bbox_region);
805 XGetWindowAttributes( disp, win, &win_attrs);
806
807 zero_list( &image_wins);
808 clip.x = 0;
809 clip.y = 0;
810 clip.width = win_attrs.width;
811 clip.height = win_attrs.height;
812 make_src_list( disp, &image_wins, bbox, win,
813 0 /* x_rootrel */, 0 /* y_rootrel */, &win_attrs, &clip);
814
815 image_regions = new_list();
816 image_only = (*allImage) ? True:False;
817
818 for (base_src = (image_win_type *) first_in_list( &image_wins); base_src;
819 base_src = (image_win_type *) next_in_list( &image_wins))
820 {
821 /* test for image visual */
822 if (!image_only || src_in_image(base_src, numImageVisuals, pImageVisuals))
823 {
824 /* find a window whose visual hasn't been put in list yet */
825 if (!src_in_region_list( base_src, image_regions))
826 {
827 if (! (new_reg = (image_region_type *)
828 malloc( sizeof( image_region_type)))) {
829 return (list_ptr) NULL;
830 }
831 count++;
832
833 new_reg->visible_region = XCreateRegion();
834 new_reg->win = base_src->win;
835 new_reg->vis = base_src->vis;
836 new_reg->cmap = base_src->cmap;
837 new_reg->x_rootrel = base_src->x_rootrel;
838 new_reg->y_rootrel = base_src->y_rootrel;
839 new_reg->x_vis = base_src->x_vis;
840 new_reg->y_vis = base_src->y_vis;
841 new_reg->width = base_src->width;
842 new_reg->height = base_src->height;
843 new_reg->border = base_src->border_width;
844
845 srcs_left = (list_ptr) dup_list_head( &image_wins, START_AT_CURR);
846 for (src = (image_win_type *) first_in_list( srcs_left); src;
847 src = (image_win_type *) next_in_list( srcs_left)) {
848 if (SAME_REGIONS( base_src, src)) {
849 add_rect_to_image_region( new_reg, src->x_vis, src->y_vis,
850 src->width, src->height);
851 }
852 else {
853 if (!image_only || src_in_image(src, numImageVisuals, pImageVisuals))
854 {
855 subtr_rect_from_image_region( new_reg, src->x_vis,
856 src->y_vis, src->width, src->height);
857 }
858 }
859 }
860 XIntersectRegion( bbox_region, new_reg->visible_region,
861 new_reg->visible_region);
862 if (! XEmptyRegion( new_reg->visible_region)) {
863 add_to_list( image_regions, new_reg);
864 if (new_reg->vis != DefaultVisualOfScreen( win_attrs.screen) ||
865 new_reg->cmap != DefaultColormapOfScreen(
866 win_attrs.screen)) {
867 *hasNonDefault = True;
868 }
869 }
870 else {
871 XDestroyRegion( new_reg->visible_region);
872 free( (void *) new_reg);
873 }
874 }
875 } else *allImage = 0;
876 }
877 delete_list( &image_wins, True);
878 XDestroyRegion( bbox_region);
879 return image_regions;
880 }
881 /** ------------------------------------------------------------------------
882 Destructor called from destroy_region_list().
883 ------------------------------------------------------------------------ **/
destroy_image_region(image_region)884 void destroy_image_region( image_region)
885 image_region_type *image_region;
886 {
887 XDestroyRegion( image_region->visible_region);
888 free( (void *) image_region);
889 }
890
891 /** ------------------------------------------------------------------------
892 Destroys the region list, destroying all the regions contained in it.
893 ------------------------------------------------------------------------ **/
destroy_region_list(rlist)894 static void destroy_region_list( rlist)
895 list_ptr rlist;
896 {
897 delete_list_destroying( rlist, (DESTRUCT_FUNC_PTR)destroy_image_region);
898 }
899
900
901 /** ------------------------------------------------------------------------
902 Subtracts the specified rectangle from the region in image_region.
903 First converts the rectangle to a region of its own, since X
904 only provides a way to subtract one region from another, not a
905 rectangle from a region.
906 ------------------------------------------------------------------------ **/
subtr_rect_from_image_region(image_region,x,y,width,height)907 static void subtr_rect_from_image_region( image_region, x, y, width, height)
908 image_region_type *image_region;
909 int x;
910 int y;
911 int width;
912 int height;
913 {
914 XRectangle rect;
915 Region rect_region;
916
917 rect_region = XCreateRegion();
918 rect.x = x;
919 rect.y = y;
920 rect.width = width;
921 rect.height = height;
922 XUnionRectWithRegion( &rect, rect_region, rect_region);
923 XSubtractRegion( image_region->visible_region, rect_region,
924 image_region->visible_region);
925 XDestroyRegion( rect_region);
926 }
927
928
929 /** ------------------------------------------------------------------------
930 Adds the specified rectangle to the region in image_region.
931 ------------------------------------------------------------------------ **/
add_rect_to_image_region(image_region,x,y,width,height)932 static void add_rect_to_image_region( image_region, x, y, width, height)
933 image_region_type *image_region;
934 int x;
935 int y;
936 int width;
937 int height;
938 {
939 XRectangle rect;
940
941 rect.x = x;
942 rect.y = y;
943 rect.width = width;
944 rect.height = height;
945 XUnionRectWithRegion( &rect, image_region->visible_region,
946 image_region->visible_region);
947 }
948
949
950 /** ------------------------------------------------------------------------
951 Returns TRUE if the given src's visual is already represented in
952 the image_regions list, FALSE otherwise.
953 ------------------------------------------------------------------------ **/
src_in_region_list(src,image_regions)954 static int src_in_region_list( src, image_regions)
955 image_win_type *src;
956 list_ptr image_regions;
957 {
958 image_region_type *ir;
959
960 for (ir = (image_region_type *) first_in_list( image_regions); ir;
961 ir = (image_region_type *) next_in_list( image_regions)) {
962 if (SAME_REGIONS( ir, src)) {
963
964 return 1;
965 }
966 }
967
968 return 0;
969 }
970
971
972 /** ------------------------------------------------------------------------
973 Makes a new entry in image_wins with the given fields filled in.
974 ------------------------------------------------------------------------ **/
add_window_to_list(image_wins,w,xrr,yrr,x_vis,y_vis,width,height,border_width,vis,cmap,parent)975 static void add_window_to_list( image_wins, w, xrr, yrr, x_vis, y_vis,
976 width, height, border_width,vis, cmap, parent)
977 list_ptr image_wins;
978 Window w;
979 int xrr;
980 int yrr;
981 int x_vis;
982 int y_vis;
983 int width;
984 int height;
985 Visual *vis;
986 Colormap cmap;
987 Window parent;
988 {
989 image_win_type *new_src;
990
991 if ((new_src = (image_win_type *) malloc( sizeof( image_win_type))) == NULL)
992
993 return;
994
995 new_src->win = w;
996 new_src->x_rootrel = xrr;
997 new_src->y_rootrel = yrr;
998 new_src->x_vis = x_vis;
999 new_src->y_vis = y_vis;
1000 new_src->width = width;
1001 new_src->height = height;
1002 new_src->border_width = border_width;
1003 new_src->vis = vis;
1004 new_src->cmap = cmap;
1005 new_src->parent = parent;
1006 add_to_list( image_wins, new_src);
1007 }
1008
1009 /** ------------------------------------------------------------------------
1010 Returns TRUE if the given src's visual is in the image planes,
1011 FALSE otherwise.
1012 ------------------------------------------------------------------------ **/
src_in_image(src,numImageVisuals,pImageVisuals)1013 static int src_in_image( src, numImageVisuals, pImageVisuals)
1014 image_win_type *src;
1015 int numImageVisuals;
1016 XVisualInfo **pImageVisuals;
1017 {
1018 int i;
1019
1020 for (i = 0 ; i < numImageVisuals ; i++)
1021 {
1022 if (pImageVisuals[i]->visual == src->vis)
1023 return 1;
1024 }
1025 return 0;
1026 }
1027
1028
1029 /** ------------------------------------------------------------------------
1030 Returns TRUE if the given src's visual is in the overlay planes
1031 and transparency is possible, FALSE otherwise.
1032 ------------------------------------------------------------------------ **/
src_in_overlay(src,numOverlayVisuals,pOverlayVisuals,transparentColor,transparentType)1033 static int src_in_overlay( src, numOverlayVisuals, pOverlayVisuals,
1034 transparentColor, transparentType)
1035 image_region_type *src;
1036 int numOverlayVisuals;
1037 OverlayInfo *pOverlayVisuals;
1038 int *transparentColor;
1039 int *transparentType;
1040 {
1041 int i;
1042
1043 for (i = 0 ; i < numOverlayVisuals ; i++)
1044 {
1045 if (((pOverlayVisuals[i].pOverlayVisualInfo)->visual == src->vis)
1046 && (pOverlayVisuals[i].transparentType != None))
1047 {
1048 *transparentColor = pOverlayVisuals[i].value;
1049 *transparentType = pOverlayVisuals[i].transparentType;
1050 return 1;
1051 }
1052
1053 else {
1054 }
1055
1056 }
1057 return 0;
1058 }
1059
1060
1061 /********************** from wsutils.c ******************************/
1062
1063 /******************************************************************************
1064 *
1065 * This file contains a set of example utility procedures; procedures that can
1066 * help a "window-smart" Starbase or PHIGS program determine information about
1067 * a device, and create image and overlay plane windows. To use these
1068 * utilities, #include "wsutils.h" and compile this file and link the results
1069 * with your program.
1070 *
1071 ******************************************************************************/
1072
1073
1074
1075 #define STATIC_GRAY 0x01
1076 #define GRAY_SCALE 0x02
1077 #define PSEUDO_COLOR 0x04
1078 #define TRUE_COLOR 0x10
1079 #define DIRECT_COLOR 0x11
1080
1081
1082 static int weCreateServerOverlayVisualsProperty = False;
1083
1084
1085 /******************************************************************************
1086 *
1087 * GetXVisualInfo()
1088 *
1089 * This routine takes an X11 Display, screen number, and returns whether the
1090 * screen supports transparent overlays and three arrays:
1091 *
1092 * 1) All of the XVisualInfo struct's for the screen.
1093 * 2) All of the OverlayInfo struct's for the screen.
1094 * 3) An array of pointers to the screen's image plane XVisualInfo
1095 * structs.
1096 *
1097 * The code below obtains the array of all the screen's visuals, and obtains
1098 * the array of all the screen's overlay visual information. It then processes
1099 * the array of the screen's visuals, determining whether the visual is an
1100 * overlay or image visual.
1101 *
1102 * If the routine sucessfully obtained the visual information, it returns zero.
1103 * If the routine didn't obtain the visual information, it returns non-zero.
1104 *
1105 ******************************************************************************/
1106
GetXVisualInfo(display,screen,transparentOverlays,numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals,numImageVisuals,pImageVisuals)1107 int GetXVisualInfo(display, screen, transparentOverlays,
1108 numVisuals, pVisuals,
1109 numOverlayVisuals, pOverlayVisuals,
1110 numImageVisuals, pImageVisuals)
1111
1112 Display *display; /* Which X server (aka "display"). */
1113 int screen; /* Which screen of the "display". */
1114 int *transparentOverlays; /* Non-zero if there's at least one
1115 * overlay visual and if at least one
1116 * of those supports a transparent
1117 * pixel. */
1118 int *numVisuals; /* Number of XVisualInfo struct's
1119 * pointed to to by pVisuals. */
1120 XVisualInfo **pVisuals; /* All of the device's visuals. */
1121 int *numOverlayVisuals; /* Number of OverlayInfo's pointed
1122 * to by pOverlayVisuals. If this
1123 * number is zero, the device does
1124 * not have overlay planes. */
1125 OverlayInfo **pOverlayVisuals; /* The device's overlay plane visual
1126 * information. */
1127 int *numImageVisuals; /* Number of XVisualInfo's pointed
1128 * to by pImageVisuals. */
1129 XVisualInfo ***pImageVisuals; /* The device's image visuals. */
1130 {
1131 XVisualInfo getVisInfo; /* Paramters of XGetVisualInfo */
1132 int mask;
1133 XVisualInfo *pVis, **pIVis; /* Faster, local copies */
1134 OverlayInfo *pOVis;
1135 OverlayVisualPropertyRec *pOOldVis;
1136 int nVisuals, nOVisuals, nIVisuals;
1137 Atom overlayVisualsAtom; /* Parameters for XGetWindowProperty */
1138 Atom actualType;
1139 unsigned long numLongs, bytesAfter;
1140 int actualFormat;
1141 int nImageVisualsAlloced; /* Values to process the XVisualInfo */
1142 int imageVisual; /* array */
1143
1144
1145 /* First, get the list of visuals for this screen. */
1146 getVisInfo.screen = screen;
1147 mask = VisualScreenMask;
1148
1149 *pVisuals = XGetVisualInfo(display, mask, &getVisInfo, numVisuals);
1150 if ((nVisuals = *numVisuals) <= 0)
1151 {
1152 /* Return that the information wasn't sucessfully obtained: */
1153 return(1);
1154 }
1155 pVis = *pVisuals;
1156
1157
1158 /* Now, get the overlay visual information for this screen. To obtain
1159 * this information, get the SERVER_OVERLAY_VISUALS property.
1160 */
1161 overlayVisualsAtom = XInternAtom(display, "SERVER_OVERLAY_VISUALS", True);
1162 if (overlayVisualsAtom != None)
1163 {
1164 /* Since the Atom exists, we can request the property's contents. The
1165 * do-while loop makes sure we get the entire list from the X server.
1166 */
1167 bytesAfter = 0;
1168 numLongs = sizeof(OverlayVisualPropertyRec) / 4;
1169 do
1170 {
1171 numLongs += bytesAfter * 4;
1172 XGetWindowProperty(display, RootWindow(display, screen),
1173 overlayVisualsAtom, 0, numLongs, False,
1174 overlayVisualsAtom, &actualType, &actualFormat,
1175 &numLongs, &bytesAfter, (unsigned char**) pOverlayVisuals);
1176 } while (bytesAfter > 0);
1177
1178
1179 /* Calculate the number of overlay visuals in the list. */
1180 *numOverlayVisuals = numLongs / (sizeof(OverlayVisualPropertyRec) / 4);
1181 }
1182 else
1183 {
1184 /* This screen doesn't have overlay planes. */
1185 *numOverlayVisuals = 0;
1186 *pOverlayVisuals = NULL;
1187 *transparentOverlays = 0;
1188 }
1189
1190
1191 /* Process the pVisuals array. */
1192 *numImageVisuals = 0;
1193 nImageVisualsAlloced = 1;
1194 pIVis = *pImageVisuals = (XVisualInfo **) malloc(sizeof(XVisualInfo *));
1195 while (--nVisuals >= 0)
1196 {
1197 nOVisuals = *numOverlayVisuals;
1198 pOVis = *pOverlayVisuals;
1199 imageVisual = True;
1200 while (--nOVisuals >= 0)
1201 {
1202 pOOldVis = (OverlayVisualPropertyRec *) pOVis;
1203 if (pVis->visualid == pOOldVis->visualID)
1204 {
1205 imageVisual = False;
1206 pOVis->pOverlayVisualInfo = pVis;
1207 if (pOVis->transparentType == TransparentPixel)
1208 *transparentOverlays = 1;
1209 }
1210 pOVis++;
1211 }
1212 if (imageVisual)
1213 {
1214 if ((*numImageVisuals += 1) > nImageVisualsAlloced)
1215 {
1216 nImageVisualsAlloced++;
1217 *pImageVisuals = (XVisualInfo **)
1218 realloc(*pImageVisuals, (nImageVisualsAlloced * sizeof(XVisualInfo *)));
1219 pIVis = *pImageVisuals + (*numImageVisuals - 1);
1220 }
1221 *pIVis++ = pVis;
1222 }
1223 pVis++;
1224 }
1225
1226
1227 /* Return that the information was sucessfully obtained: */
1228 return(0);
1229
1230 } /* GetXVisualInfo() */
1231
1232
1233 /******************************************************************************
1234 *
1235 * FreeXVisualInfo()
1236 *
1237 * This routine frees the data that was allocated by GetXVisualInfo().
1238 *
1239 ******************************************************************************/
1240
FreeXVisualInfo(pVisuals,pOverlayVisuals,pImageVisuals)1241 void FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals)
1242
1243 XVisualInfo *pVisuals;
1244 OverlayInfo *pOverlayVisuals;
1245 XVisualInfo **pImageVisuals;
1246 {
1247 XFree(pVisuals);
1248 if (weCreateServerOverlayVisualsProperty)
1249 free(pOverlayVisuals);
1250 else
1251 XFree(pOverlayVisuals);
1252 free(pImageVisuals);
1253
1254 } /* FreeXVisualInfo() */
1255