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