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