multiVis.c revision 5e358eca
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
1735e358ecaSmrgvoid initFakeVisual(Visual *Vis)
174b3307321Smrg{
175b3307321Smrg    Vis->ext_data=NULL;
176b3307321Smrg    Vis->class = DirectColor ;
177b3307321Smrg    Vis->red_mask =   0x00FF0000;
178b3307321Smrg    Vis->green_mask = 0x0000FF00 ;
179b3307321Smrg    Vis->blue_mask  = 0x000000FF ;
180b3307321Smrg    Vis->map_entries = 256 ;
181b3307321Smrg    Vis->bits_per_rgb = 8 ;
182b3307321Smrg}
183b3307321Smrg
184b3307321Smrgstatic int
1855e358ecaSmrgQueryColorMap(Display *disp, Colormap src_cmap, Visual *src_vis,
1865e358ecaSmrg	      XColor **src_colors, int *rShift, int *gShift, int *bShift)
187b3307321Smrg{
188b3307321Smrg     int ncolors,i ;
189b3307321Smrg     unsigned long       redMask, greenMask, blueMask;
190b3307321Smrg     int                 redShift, greenShift, blueShift;
191b3307321Smrg     XColor *colors ;
192b3307321Smrg
193b3307321Smrg     ncolors = src_vis->map_entries ;
194b3307321Smrg     *src_colors = colors = (XColor *)malloc(ncolors * sizeof(XColor) ) ;
195b3307321Smrg
196b3307321Smrg     if(src_vis->class != TrueColor && src_vis->class != DirectColor)
197b3307321Smrg     {
198b3307321Smrg         for(i=0 ; i < ncolors ; i++)
199b3307321Smrg         {
200b3307321Smrg	        colors[i].pixel = i ;
201b3307321Smrg                colors[i].pad = 0;
202b3307321Smrg                colors[i].flags = DoRed|DoGreen|DoBlue;
203b3307321Smrg         }
204b3307321Smrg     }
205b3307321Smrg     else /** src is decomposed rgb ***/
206b3307321Smrg     {
207b3307321Smrg        /* Get the X colormap */
208b3307321Smrg        redMask = src_vis->red_mask;
209b3307321Smrg        greenMask = src_vis->green_mask;
210b3307321Smrg        blueMask = src_vis->blue_mask;
211b3307321Smrg        redShift = 0; while (!(redMask&0x1)) {
212b3307321Smrg                redShift++;
213b3307321Smrg                redMask = redMask>>1;
214b3307321Smrg        }
215b3307321Smrg        greenShift = 0; while (!(greenMask&0x1)) {
216b3307321Smrg                greenShift++;
217b3307321Smrg                greenMask = greenMask>>1;
218b3307321Smrg        }
219b3307321Smrg        blueShift = 0; while (!(blueMask&0x1)) {
220b3307321Smrg                blueShift++;
221b3307321Smrg                blueMask = blueMask>>1;
222b3307321Smrg        }
223b3307321Smrg	*rShift = redShift ;
224b3307321Smrg	*gShift = greenShift ;
225b3307321Smrg	*bShift = blueShift ;
226b3307321Smrg        for (i=0; i<ncolors; i++) {
227b3307321Smrg		if( i <= redMask)colors[i].pixel = (i<<redShift) ;
228b3307321Smrg		if( i <= greenMask)colors[i].pixel |= (i<<greenShift) ;
229b3307321Smrg		if( i <= blueMask)colors[i].pixel |= (i<<blueShift) ;
230b3307321Smrg		/***** example :for gecko's 3-3-2 map, blue index should be <= 3.
231b3307321Smrg                colors[i].pixel = (i<<redShift)|(i<<greenShift)|(i<<blueShift);
232b3307321Smrg		*****/
233b3307321Smrg                colors[i].pad = 0;
234b3307321Smrg                colors[i].flags = DoRed|DoGreen|DoBlue;
235b3307321Smrg        }
236b3307321Smrg      }
237b3307321Smrg
238b3307321Smrg
239b3307321Smrg      XQueryColors(disp, src_cmap, colors, ncolors);
240b3307321Smrg      return ncolors ;
241b3307321Smrg}
242b3307321Smrg
243b3307321Smrgint
2445e358ecaSmrgGetMultiVisualRegions(Display *disp,
2455e358ecaSmrg		      /* root win on which grab was done */
2465e358ecaSmrg		      Window srcRootWinid,
2475e358ecaSmrg		      /* root rel UL corner of bounding box of grab */
2485e358ecaSmrg		      int x, int y,
2495e358ecaSmrg		      /* size of bounding box of grab */
2505e358ecaSmrg		      unsigned int width, unsigned int height,
2515e358ecaSmrg		      int *transparentOverlays, int *numVisuals,
2525e358ecaSmrg		      XVisualInfo **pVisuals, int *numOverlayVisuals,
2535e358ecaSmrg		      OverlayInfo **pOverlayVisuals,
2545e358ecaSmrg		      int *numImageVisuals, XVisualInfo ***pImageVisuals,
2555e358ecaSmrg		      /* list of regions to read from */
2565e358ecaSmrg		      list_ptr *vis_regions,
2575e358ecaSmrg		      list_ptr *vis_image_regions, int *allImage)
258b3307321Smrg{
259b3307321Smrg    int                 hasNonDefault;
260b3307321Smrg    XRectangle          bbox;           /* bounding box of grabbed area */
261b3307321Smrg
262b3307321Smrg
263b3307321Smrg    bbox.x = x;                 /* init X rect for bounding box */
264b3307321Smrg    bbox.y = y;
265b3307321Smrg    bbox.width = width;
266b3307321Smrg    bbox.height = height;
267b3307321Smrg
268b3307321Smrg    GetXVisualInfo(disp,DefaultScreen(disp),
269b3307321Smrg                    transparentOverlays,
270b3307321Smrg                    numVisuals, pVisuals,
271b3307321Smrg                    numOverlayVisuals, pOverlayVisuals,
272b3307321Smrg                    numImageVisuals, pImageVisuals);
273b3307321Smrg
274b3307321Smrg    *vis_regions = *vis_image_regions = NULL ;
275b3307321Smrg    if ((*vis_regions = make_region_list( disp, srcRootWinid, &bbox,
276b3307321Smrg                                         &hasNonDefault, *numImageVisuals,
277b3307321Smrg                                         *pImageVisuals, allImage)) == NULL)
278b3307321Smrg    	return 0 ;
279b3307321Smrg
280b3307321Smrg    if (*transparentOverlays)
281b3307321Smrg    {
282b3307321Smrg        *allImage = 1; /* until proven otherwise,
283b3307321Smrg                         this flags that it to be an image only list */
284b3307321Smrg        *vis_image_regions =
285b3307321Smrg                make_region_list( disp, srcRootWinid, &bbox, &hasNonDefault,
286b3307321Smrg                                        *numImageVisuals, *pImageVisuals, allImage);
287b3307321Smrg    }
288b3307321Smrg
289b3307321Smrg    /* if there is a second region in any of the two lists return 1 **/
290b3307321Smrg    if ( ( *vis_regions && (*vis_regions)->next && (*vis_regions)->next->next ) ||
291b3307321Smrg         ( *vis_image_regions && (*vis_image_regions)->next &&
292b3307321Smrg           (*vis_image_regions)->next->next ) ) return 1 ;
293b3307321Smrg    else return 0 ;
294b3307321Smrg
295b3307321Smrg}
296b3307321Smrg
2975e358ecaSmrgstatic void TransferImage(Display *disp, XImage *reg_image,
2985e358ecaSmrg			  int srcw, int srch,
2995e358ecaSmrg			  image_region_type *reg, XImage *target_image,
3005e358ecaSmrg			  int dst_x, int dst_y)
301b3307321Smrg{
302b3307321Smrg    int i,j,old_pixel,new_pixel,red_ind,green_ind,blue_ind ;
303b3307321Smrg    XColor *colors;
304b3307321Smrg    int rShift,gShift,bShift;
305b3307321Smrg
306b3307321Smrg    (void) QueryColorMap(disp,reg->cmap,reg->vis,&colors,
307b3307321Smrg	 &rShift,&gShift,&bShift) ;
308b3307321Smrg
309b3307321Smrg    switch (reg->vis->class) {
310b3307321Smrg    case TrueColor :
311b3307321Smrg       for(i=0 ; i < srch ; i++)
312b3307321Smrg       {
313b3307321Smrg         for(j=0 ; j < srcw ;  j++)
314b3307321Smrg         {
315b3307321Smrg	   old_pixel = XGetPixel(reg_image,j,i) ;
316b3307321Smrg
317b3307321Smrg           if( reg->vis->map_entries == 16) {
318b3307321Smrg
319b3307321Smrg                 red_ind = (old_pixel & reg->vis->red_mask) >> rShift ;
320b3307321Smrg	         green_ind = (old_pixel & reg->vis->green_mask) >> gShift ;
321b3307321Smrg	         blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ;
322b3307321Smrg
323b3307321Smrg	         new_pixel = (
324b3307321Smrg			      ((colors[red_ind].red >> 8) << RED_SHIFT)
325b3307321Smrg			      |((colors[green_ind].green >> 8) << GREEN_SHIFT)
326b3307321Smrg			      |((colors[blue_ind].blue >> 8) << BLUE_SHIFT)
327b3307321Smrg                             );
328b3307321Smrg           }
329b3307321Smrg	   else
330b3307321Smrg		new_pixel = old_pixel;
331b3307321Smrg
332b3307321Smrg           XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
333b3307321Smrg
334b3307321Smrg         }
335b3307321Smrg       }
336b3307321Smrg       break;
337b3307321Smrg    case DirectColor :
338b3307321Smrg       for(i=0 ; i < srch ; i++)
339b3307321Smrg       {
340b3307321Smrg
341b3307321Smrg         for(j=0 ; j < srcw ;  j++)
342b3307321Smrg         {
343b3307321Smrg	   old_pixel = XGetPixel(reg_image,j,i) ;
344b3307321Smrg           red_ind = (old_pixel & reg->vis->red_mask) >> rShift ;
345b3307321Smrg	   green_ind = (old_pixel & reg->vis->green_mask) >> gShift ;
346b3307321Smrg	   blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ;
347b3307321Smrg
348b3307321Smrg	   new_pixel = (
349b3307321Smrg			 ((colors[red_ind].red >> 8) << RED_SHIFT)
350b3307321Smrg			|((colors[green_ind].green >> 8) << GREEN_SHIFT)
351b3307321Smrg			|((colors[blue_ind].blue >> 8) << BLUE_SHIFT)
352b3307321Smrg                       );
353b3307321Smrg           XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
354b3307321Smrg
355b3307321Smrg         }
356b3307321Smrg       }
357b3307321Smrg       break;
358b3307321Smrg    default :
359b3307321Smrg       for(i=0 ; i < srch ; i++)
360b3307321Smrg       {
361b3307321Smrg         for(j=0 ; j < srcw ;  j++)
362b3307321Smrg         {
363b3307321Smrg	    old_pixel = XGetPixel(reg_image,j,i) ;
364b3307321Smrg
365b3307321Smrg	   new_pixel = (
366b3307321Smrg			 ((colors[old_pixel].red >> 8) << RED_SHIFT)
367b3307321Smrg			|((colors[old_pixel].green >> 8) << GREEN_SHIFT)
368b3307321Smrg			|((colors[old_pixel].blue >> 8) << BLUE_SHIFT)
369b3307321Smrg                       );
370b3307321Smrg           XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
371b3307321Smrg
372b3307321Smrg         }
373b3307321Smrg       }
374b3307321Smrg       break;
375b3307321Smrg    }
376b3307321Smrg}
377b3307321Smrg
378b3307321Smrgstatic XImage *
3795e358ecaSmrgReadRegionsInList(Display *disp, Visual *fakeVis, int depth, int format,
3805e358ecaSmrg		  int width,int height,
3815e358ecaSmrg		  XRectangle bbox,	/* bounding box of grabbed area */
3825e358ecaSmrg		  list_ptr regions)	/* list of regions to read from */
383b3307321Smrg{
384b3307321Smrg    image_region_type	*reg;
385b3307321Smrg    int			dst_x, dst_y;	/* where in pixmap to write (UL) */
386b3307321Smrg    int			diff;
387b3307321Smrg
388b3307321Smrg    XImage		*reg_image,*ximage ;
389b3307321Smrg    int			srcRect_x,srcRect_y,srcRect_width,srcRect_height ;
390b3307321Smrg    int                 rem ;
391b3307321Smrg    int                 bytes_per_line;
392b3307321Smrg    int                 bitmap_unit;
393b3307321Smrg
394b3307321Smrg    bitmap_unit = sizeof (long);
395b3307321Smrg    if (format == ZPixmap)
396b3307321Smrg       bytes_per_line = width*depth/8;
397b3307321Smrg    else
398b3307321Smrg       bytes_per_line = width/8;
399b3307321Smrg
400b3307321Smrg
401b3307321Smrg    /* Find out how many more bytes are required for padding so that
402b3307321Smrg    ** bytes per scan line will be multiples of bitmap_unit bits */
403b3307321Smrg    if (format == ZPixmap) {
404b3307321Smrg       rem = (bytes_per_line*8)%bitmap_unit;
405b3307321Smrg    if (rem)
406b3307321Smrg       bytes_per_line += (rem/8 + 1);
407b3307321Smrg    }
408b3307321Smrg
409b3307321Smrg    ximage = XCreateImage(disp,fakeVis,depth,format,0,NULL,width,height,
410b3307321Smrg	         8,0) ;
411b3307321Smrg    bytes_per_line = ximage->bytes_per_line;
412b3307321Smrg
413b3307321Smrg    if (format == ZPixmap)
414b3307321Smrg    	  ximage->data = malloc(height*bytes_per_line);
415b3307321Smrg    else
416b3307321Smrg        ximage->data = malloc(height*bytes_per_line*depth);
417b3307321Smrg
418b3307321Smrg    ximage->bits_per_pixel = depth; /** Valid only if format is ZPixmap ***/
419b3307321Smrg
420b3307321Smrg    for (reg = (image_region_type *) first_in_list( regions); reg;
421b3307321Smrg	 reg = (image_region_type *) next_in_list( regions))
422b3307321Smrg    {
423b3307321Smrg		int rect;
424b3307321Smrg		struct my_XRegion *vis_reg;
425b3307321Smrg		vis_reg = (struct my_XRegion *)(reg->visible_region);
426b3307321Smrg		for (rect = 0;
427b3307321Smrg		     rect < vis_reg->numRects;
428b3307321Smrg		     rect++)
429b3307321Smrg		{
430b3307321Smrg		/** ------------------------------------------------------------------------
431b3307321Smrg			Intersect bbox with visible part of region giving src rect & output
432b3307321Smrg			location.  Width is the min right side minus the max left side.
433b3307321Smrg			Similar for height.  Offset src rect so x,y are relative to
434b3307321Smrg			origin of win, not the root-relative visible rect of win.
435b3307321Smrg		    ------------------------------------------------------------------------ **/
436b3307321Smrg		    srcRect_width  = MIN( vis_reg->rects[rect].x2, bbox.width + bbox.x) -
437b3307321Smrg				     MAX( vis_reg->rects[rect].x1, bbox.x);
438b3307321Smrg		    srcRect_height = MIN( vis_reg->rects[rect].y2, bbox.height + bbox.y) -
439b3307321Smrg				     MAX( vis_reg->rects[rect].y1, bbox.y);
440b3307321Smrg		    diff = bbox.x - vis_reg->rects[rect].x1;
441b3307321Smrg		    srcRect_x = MAX( 0, diff)  + (vis_reg->rects[rect].x1 - reg->x_rootrel - reg->border);
442b3307321Smrg		    dst_x     = MAX( 0, -diff) ;
443b3307321Smrg		    diff = bbox.y - vis_reg->rects[rect].y1;
444b3307321Smrg		    srcRect_y = MAX( 0, diff)  + (vis_reg->rects[rect].y1 - reg->y_rootrel - reg->border);
445b3307321Smrg		    dst_y     = MAX( 0, -diff) ;
446b3307321Smrg                    reg_image = XGetImage(disp,reg->win,srcRect_x,srcRect_y,
447b3307321Smrg				srcRect_width,srcRect_height,AllPlanes,format) ;
448b3307321Smrg		    TransferImage(disp,reg_image,srcRect_width,
449b3307321Smrg		                 srcRect_height,reg,ximage,dst_x,dst_y) ;
450b3307321Smrg	    }
451b3307321Smrg    }
452b3307321Smrg    return ximage ;
453b3307321Smrg}
454b3307321Smrg
455b3307321Smrg
456b3307321Smrg/** ------------------------------------------------------------------------
457b3307321Smrg    ------------------------------------------------------------------------ **/
458b3307321Smrg
4595e358ecaSmrgXImage *ReadAreaToImage(Display *disp,
4605e358ecaSmrg			/* root win on which grab was done */
4615e358ecaSmrg			Window srcRootWinid,
4625e358ecaSmrg			/* root rel UL corner of bounding box of grab */
4635e358ecaSmrg			int x, int y,
4645e358ecaSmrg			/* size of bounding box of grab */
4655e358ecaSmrg			unsigned int width, unsigned int height,
4665e358ecaSmrg			int numVisuals, XVisualInfo *pVisuals,
4675e358ecaSmrg			int numOverlayVisuals, OverlayInfo *pOverlayVisuals,
4685e358ecaSmrg			int numImageVisuals, XVisualInfo **pImageVisuals,
4695e358ecaSmrg			/* list of regions to read from */
4705e358ecaSmrg			list_ptr vis_regions,
4715e358ecaSmrg			/* list of regions to read from */
4725e358ecaSmrg			list_ptr vis_image_regions,
4735e358ecaSmrg			int format, int allImage)
474b3307321Smrg{
475b3307321Smrg    image_region_type	*reg;
476b3307321Smrg    XRectangle		bbox;		/* bounding box of grabbed area */
477b3307321Smrg    int 		depth ;
478b3307321Smrg    XImage		*ximage, *ximage_ipm = NULL;
479b3307321Smrg    Visual		fakeVis ;
480b3307321Smrg    int 	x1, y1;
481b3307321Smrg    XImage	*image;
482b3307321Smrg#if 0
483b3307321Smrg    unsigned char 	*pmData ,  *ipmData ;
484b3307321Smrg#endif
485b3307321Smrg    int                 transparentColor, transparentType;
486b3307321Smrg    int			srcRect_x,srcRect_y,srcRect_width,srcRect_height ;
487b3307321Smrg    int			diff ;
488b3307321Smrg    int			dst_x, dst_y;	/* where in pixmap to write (UL) */
489b3307321Smrg    int			pixel;
490b3307321Smrg
491b3307321Smrg    bbox.x = x;			/* init X rect for bounding box */
492b3307321Smrg    bbox.y = y;
493b3307321Smrg    bbox.width = width;
494b3307321Smrg    bbox.height = height;
495b3307321Smrg
496b3307321Smrg
497b3307321Smrg    initFakeVisual(&fakeVis) ;
498b3307321Smrg
499b3307321Smrg    depth = 24 ;
500b3307321Smrg    ximage = ReadRegionsInList(disp,&fakeVis,depth,format,width,height,
501b3307321Smrg	     bbox,vis_regions) ;
502b3307321Smrg#if 0
503b3307321Smrg    pmData = (unsigned char *)ximage -> data ;
504b3307321Smrg#endif
505b3307321Smrg
506b3307321Smrg/* if transparency possible do it again, but this time for image planes only */
507b3307321Smrg    if (vis_image_regions && (vis_image_regions->next) && !allImage)
508b3307321Smrg    {
509b3307321Smrg	ximage_ipm = ReadRegionsInList(disp,&fakeVis,depth,format,width,height,
510b3307321Smrg		     bbox,vis_image_regions) ;
511b3307321Smrg#if 0
512b3307321Smrg        ipmData = (unsigned char *)ximage_ipm -> data ;
513b3307321Smrg#endif
514b3307321Smrg    }
515b3307321Smrg/* Now tranverse the overlay visual windows and test for transparency index.  */
516b3307321Smrg/* If you find one, subsitute the value from the matching image plane pixmap. */
517b3307321Smrg
518b3307321Smrg    for (reg = (image_region_type *) first_in_list( vis_regions); reg;
519b3307321Smrg	 reg = (image_region_type *) next_in_list( vis_regions))
520b3307321Smrg    {
521b3307321Smrg
522b3307321Smrg	if (src_in_overlay( reg, numOverlayVisuals, pOverlayVisuals,
523b3307321Smrg				 &transparentColor, &transparentType))
524b3307321Smrg	{
525b3307321Smrg	int test = 0 ;
526b3307321Smrg	     srcRect_width  = MIN( reg->width + reg->x_vis, bbox.width + bbox.x)
527b3307321Smrg				 - MAX( reg->x_vis, bbox.x);
528b3307321Smrg	     srcRect_height = MIN( reg->height + reg->y_vis, bbox.height
529b3307321Smrg				 + bbox.y) - MAX( reg->y_vis, bbox.y);
530b3307321Smrg             diff = bbox.x - reg->x_vis;
531b3307321Smrg             srcRect_x = MAX( 0, diff)  + (reg->x_vis - reg->x_rootrel - reg->border);
532b3307321Smrg             dst_x     = MAX( 0, -diff) ;
533b3307321Smrg	     diff = bbox.y - reg->y_vis;
534b3307321Smrg	     srcRect_y = MAX( 0, diff)  + (reg->y_vis - reg->y_rootrel - reg->border);
535b3307321Smrg	     dst_y     = MAX( 0, -diff) ;
536b3307321Smrg	/* let's test some pixels for transparency */
537b3307321Smrg             image = XGetImage(disp, reg->win, srcRect_x, srcRect_y,
538b3307321Smrg		 srcRect_width, srcRect_height, 0xffffffff, ZPixmap);
539b3307321Smrg
540b3307321Smrg        /* let's assume byte per pixel for overlay image for now */
541b3307321Smrg	     if ((image->depth == 8) && (transparentType == TransparentPixel))
542b3307321Smrg	     {
543b3307321Smrg	         unsigned char *pixel_ptr;
544b3307321Smrg	         unsigned char *start_of_line = (unsigned char *) image->data;
545b3307321Smrg
546b3307321Smrg	         for (y1 = 0; y1 < srcRect_height; y1++) {
547b3307321Smrg		    pixel_ptr = start_of_line;
548b3307321Smrg		    for (x1 = 0; x1 < srcRect_width; x1++)
549b3307321Smrg		    {
550b3307321Smrg			if (*pixel_ptr++ == transparentColor)
551b3307321Smrg			{
552b3307321Smrg#if 0
553b3307321Smrg			    *pmData++ = *ipmData++;
554b3307321Smrg			    *pmData++ = *ipmData++;
555b3307321Smrg			    *pmData++ = *ipmData++;
556b3307321Smrg#endif
557b3307321Smrg	                pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
558b3307321Smrg                        XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
559b3307321Smrg
560b3307321Smrg			if(!test){
561b3307321Smrg			   test = 1 ;
562b3307321Smrg			}
563b3307321Smrg			}
564b3307321Smrg#if 0
565b3307321Smrg			else {
566b3307321Smrg			    pmData +=3;
567b3307321Smrg			    ipmData +=3;
568b3307321Smrg			}
569b3307321Smrg#endif
570b3307321Smrg		    }
571b3307321Smrg		    start_of_line += image->bytes_per_line;
572b3307321Smrg		}
573b3307321Smrg	} else {
574b3307321Smrg		if (transparentType == TransparentPixel) {
575b3307321Smrg		for (y1 = 0; y1 < srcRect_height; y1++) {
576b3307321Smrg		      for (x1 = 0; x1 < srcRect_width; x1++)
577b3307321Smrg		      {
578b3307321Smrg			    int pixel_value = XGetPixel(image, x1, y1);
579b3307321Smrg			    if (pixel_value == transparentColor)
580b3307321Smrg			    {
581b3307321Smrg#if 0
582b3307321Smrg				*pmData++ = *ipmData++;
583b3307321Smrg				*pmData++ = *ipmData++;
584b3307321Smrg				*pmData++ = *ipmData++;
585b3307321Smrg#endif
586b3307321Smrg	                pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
587b3307321Smrg                        XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
588b3307321Smrg			if(!test){
589b3307321Smrg			   test = 1 ;
590b3307321Smrg			}
591b3307321Smrg			    }
592b3307321Smrg#if 0
593b3307321Smrg			    else {
594b3307321Smrg				pmData +=3;
595b3307321Smrg				ipmData +=3;
596b3307321Smrg			    }
597b3307321Smrg#endif
598b3307321Smrg			}
599b3307321Smrg		    }
600b3307321Smrg		} else {
601b3307321Smrg		    for (y1 = 0; y1 < srcRect_height; y1++) {
602b3307321Smrg			for (x1 = 0; x1 < srcRect_width; x1++)
603b3307321Smrg			{
604b3307321Smrg			    int pixel_value = XGetPixel(image, x1, y1);
605b3307321Smrg			    if (pixel_value & transparentColor)
606b3307321Smrg			    {
607b3307321Smrg#if 0
608b3307321Smrg				*pmData++ = *ipmData++;
609b3307321Smrg				*pmData++ = *ipmData++;
610b3307321Smrg				*pmData++ = *ipmData++;
611b3307321Smrg#endif
612b3307321Smrg	                        pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
613b3307321Smrg                                XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
614b3307321Smrg			if(!test){
615b3307321Smrg			   test = 1 ;
616b3307321Smrg			}
617b3307321Smrg			    }
618b3307321Smrg#if 0
619b3307321Smrg			    else {
620b3307321Smrg				pmData +=3;
621b3307321Smrg				ipmData +=3;
622b3307321Smrg			    }
623b3307321Smrg#endif
624b3307321Smrg			}
625b3307321Smrg		    }
626b3307321Smrg		}
627b3307321Smrg	}
628b3307321Smrg        XDestroyImage (image);
629b3307321Smrg      }	/* end of src_in_overlay */
630b3307321Smrg    } /** end transparency **/
631b3307321Smrg    destroy_region_list( vis_regions);
632b3307321Smrg    if (vis_image_regions) destroy_region_list( vis_image_regions );
633b3307321Smrg    FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals);
634b3307321Smrg    XSync(disp, 0);
635b3307321Smrg
636b3307321Smrg    return ximage;
637b3307321Smrg}
638b3307321Smrg
639b3307321Smrg/** ------------------------------------------------------------------------
640b3307321Smrg	Creates a list of the subwindows of a given window which have a
641b3307321Smrg	different visual than their parents.  The function is recursive.
642b3307321Smrg	This list is used in make_region_list(), which coalesces the
643b3307321Smrg	windows with the same visual into a region.
644b3307321Smrg	image_wins must point to an existing list struct that's already
645b3307321Smrg	been zeroed (zero_list()).
646b3307321Smrg    ------------------------------------------------------------------------ **/
6475e358ecaSmrgstatic void make_src_list(Display *disp, list_ptr image_wins,
6485e358ecaSmrg			  /* bnding box of area we want */
6495e358ecaSmrg			  XRectangle *bbox,
6505e358ecaSmrg			  Window curr,
6515e358ecaSmrg			  /* pos of curr WRT root */
6525e358ecaSmrg			  int x_rootrel, int y_rootrel,
6535e358ecaSmrg			  XWindowAttributes *curr_attrs,
6545e358ecaSmrg			  /* visible part of curr, not obscurred by ancestors */
6555e358ecaSmrg			  XRectangle *pclip)
656b3307321Smrg{
657b3307321Smrg    XWindowAttributes child_attrs;
658b3307321Smrg    Window root, parent, *child;	/* variables for XQueryTree() */
659b3307321Smrg    Window *save_child_list;		/* variables for XQueryTree() */
660b3307321Smrg    unsigned int nchild;		/* variables for XQueryTree() */
661b3307321Smrg    XRectangle child_clip;		/* vis part of child */
662b3307321Smrg    int curr_clipX, curr_clipY, curr_clipRt, curr_clipBt;
663b3307321Smrg
664b3307321Smrg    /* check that win is mapped & not outside bounding box */
665b3307321Smrg    if (curr_attrs->map_state == IsViewable &&
666b3307321Smrg	curr_attrs->class == InputOutput &&
667b3307321Smrg	!( pclip->x >= (int) (bbox->x + bbox->width)	||
668b3307321Smrg	   pclip->y >= (int) (bbox->y + bbox->height)	||
669b3307321Smrg	   (int) (pclip->x + pclip->width)  <= bbox->x	||
670b3307321Smrg	   (int) (pclip->y + pclip->height) <= bbox->y)) {
671b3307321Smrg
672b3307321Smrg	XQueryTree( disp, curr, &root, &parent, &child, &nchild );
673b3307321Smrg	save_child_list = child;      /* so we can free list when we're done */
674b3307321Smrg	add_window_to_list( image_wins, curr, x_rootrel, y_rootrel,
675b3307321Smrg			    pclip->x, pclip->y,
676b3307321Smrg			    pclip->width, pclip->height,
677b3307321Smrg			    curr_attrs->border_width,curr_attrs->visual,
678b3307321Smrg			    curr_attrs->colormap, parent);
679b3307321Smrg
680b3307321Smrg
681b3307321Smrg/** ------------------------------------------------------------------------
682b3307321Smrg	set RR coords of right (Rt), left (X), bottom (Bt) and top (Y)
683b3307321Smrg	of rect we clip all children by.  This is our own clip rect (pclip)
684b3307321Smrg	inflicted on us by our parent plus our own borders.  Within the
685b3307321Smrg	child loop, we figure the clip rect for each child by adding in
686b3307321Smrg	it's rectangle (not taking into account the child's borders).
687b3307321Smrg    ------------------------------------------------------------------------ **/
688b3307321Smrg	curr_clipX = MAX( pclip->x, x_rootrel + (int) curr_attrs->border_width);
689b3307321Smrg	curr_clipY = MAX( pclip->y, y_rootrel + (int) curr_attrs->border_width);
690b3307321Smrg	curr_clipRt = MIN( pclip->x + (int) pclip->width,
691b3307321Smrg			   x_rootrel + (int) curr_attrs->width +
692b3307321Smrg			   2 * (int) curr_attrs->border_width);
693b3307321Smrg	curr_clipBt = MIN( pclip->y + (int) pclip->height,
694b3307321Smrg			   y_rootrel + (int) curr_attrs->height +
695b3307321Smrg			   2 * (int) curr_attrs->border_width);
696b3307321Smrg
697b3307321Smrg	while (nchild--) {
698b3307321Smrg	    int new_width, new_height;
699b3307321Smrg	    int child_xrr, child_yrr;	/* root relative x & y of child */
700b3307321Smrg
701b3307321Smrg	    XGetWindowAttributes( disp, *child, &child_attrs);
702b3307321Smrg
703b3307321Smrg	    /* intersect parent & child clip rects */
704b3307321Smrg	    child_xrr = x_rootrel + child_attrs.x + curr_attrs->border_width;
705b3307321Smrg	    child_clip.x = MAX( curr_clipX, child_xrr);
706b3307321Smrg	    new_width = MIN( curr_clipRt, child_xrr + (int) child_attrs.width
707b3307321Smrg			     + 2 * child_attrs.border_width)
708b3307321Smrg			- child_clip.x;
709b3307321Smrg	    if (new_width >= 0) {
710b3307321Smrg		child_clip.width = new_width;
711b3307321Smrg
712b3307321Smrg		child_yrr = y_rootrel + child_attrs.y +
713b3307321Smrg			    curr_attrs->border_width;
714b3307321Smrg		child_clip.y = MAX( curr_clipY, child_yrr);
715b3307321Smrg		new_height = MIN( curr_clipBt,
716b3307321Smrg				  child_yrr + (int) child_attrs.height +
717b3307321Smrg				      2 * child_attrs.border_width)
718b3307321Smrg			     - child_clip.y;
719b3307321Smrg		if (new_height >= 0) {
720b3307321Smrg		    child_clip.height = new_height;
721b3307321Smrg		    make_src_list( disp, image_wins, bbox, *child,
722b3307321Smrg				   child_xrr, child_yrr,
723b3307321Smrg				   &child_attrs, &child_clip);
724b3307321Smrg		}
725b3307321Smrg	    }
726b3307321Smrg	    child++;
727b3307321Smrg	}
728b3307321Smrg	XFree( save_child_list);
729b3307321Smrg    }
730b3307321Smrg}
731b3307321Smrg
732b3307321Smrg
733b3307321Smrg/** ------------------------------------------------------------------------
734b3307321Smrg	This function creates a list of regions which tile a specified
735b3307321Smrg	window.  Each region contains all visible portions of the window
736b3307321Smrg	which are drawn with the same visual.  For example, if the
737b3307321Smrg	window consists of subwindows of two different visual types,
738b3307321Smrg	there will be two regions in the list.
739b3307321Smrg	Returns a pointer to the list.
740b3307321Smrg    ------------------------------------------------------------------------ **/
7415e358ecaSmrgstatic list_ptr make_region_list(Display *disp, Window win, XRectangle *bbox,
7425e358ecaSmrg				 int *hasNonDefault, int numImageVisuals,
7435e358ecaSmrg				 XVisualInfo **pImageVisuals, int *allImage)
744b3307321Smrg{
745b3307321Smrg    XWindowAttributes	win_attrs;
746b3307321Smrg    list		image_wins;
747b3307321Smrg    list_ptr		image_regions;
748b3307321Smrg    list_ptr		srcs_left;
749b3307321Smrg    image_region_type	*new_reg;
750b3307321Smrg    image_win_type	*base_src, *src;
751b3307321Smrg    Region		bbox_region = XCreateRegion();
752b3307321Smrg    XRectangle		clip;
753b3307321Smrg    int			image_only;
754b3307321Smrg
755b3307321Smrg    int                 count=0 ;
756b3307321Smrg
757b3307321Smrg    *hasNonDefault = False;
758b3307321Smrg    XUnionRectWithRegion( bbox, bbox_region, bbox_region);
759b3307321Smrg    XGetWindowAttributes( disp, win, &win_attrs);
760b3307321Smrg
761b3307321Smrg    zero_list( &image_wins);
762b3307321Smrg    clip.x = 0;
763b3307321Smrg    clip.y = 0;
764b3307321Smrg    clip.width  = win_attrs.width;
765b3307321Smrg    clip.height = win_attrs.height;
766b3307321Smrg    make_src_list( disp, &image_wins, bbox, win,
767b3307321Smrg		   0 /* x_rootrel */, 0 /* y_rootrel */, &win_attrs, &clip);
768b3307321Smrg
769b3307321Smrg    image_regions = new_list();
770b3307321Smrg    image_only = (*allImage) ? True:False;
771b3307321Smrg
772b3307321Smrg    for (base_src = (image_win_type *) first_in_list( &image_wins); base_src;
773b3307321Smrg	 base_src = (image_win_type *) next_in_list( &image_wins))
774b3307321Smrg    {
775b3307321Smrg	/* test for image visual */
776b3307321Smrg	if (!image_only || src_in_image(base_src, numImageVisuals, pImageVisuals))
777b3307321Smrg	{
778b3307321Smrg	    /* find a window whose visual hasn't been put in list yet */
779b3307321Smrg	    if (!src_in_region_list( base_src, image_regions))
780b3307321Smrg	    {
781b3307321Smrg		if (! (new_reg = (image_region_type *)
782b3307321Smrg					malloc( sizeof( image_region_type)))) {
783b3307321Smrg		    return (list_ptr) NULL;
784b3307321Smrg		}
785b3307321Smrg		count++;
786b3307321Smrg
787b3307321Smrg		new_reg->visible_region = XCreateRegion();
788b3307321Smrg		new_reg->win		= base_src->win;
789b3307321Smrg		new_reg->vis		= base_src->vis;
790b3307321Smrg		new_reg->cmap	 	= base_src->cmap;
791b3307321Smrg		new_reg->x_rootrel	= base_src->x_rootrel;
792b3307321Smrg		new_reg->y_rootrel	= base_src->y_rootrel;
793b3307321Smrg		new_reg->x_vis		= base_src->x_vis;
794b3307321Smrg		new_reg->y_vis		= base_src->y_vis;
795b3307321Smrg		new_reg->width		= base_src->width;
796b3307321Smrg		new_reg->height		= base_src->height;
797b3307321Smrg		new_reg->border		= base_src->border_width;
798b3307321Smrg
799b3307321Smrg		srcs_left = (list_ptr) dup_list_head( &image_wins, START_AT_CURR);
800b3307321Smrg		for (src = (image_win_type *) first_in_list( srcs_left); src;
801b3307321Smrg		     src = (image_win_type *) next_in_list( srcs_left)) {
802b3307321Smrg		    if (SAME_REGIONS( base_src, src)) {
803b3307321Smrg			add_rect_to_image_region( new_reg, src->x_vis, src->y_vis,
804b3307321Smrg						  src->width, src->height);
805b3307321Smrg		    }
806b3307321Smrg		    else {
807b3307321Smrg			if (!image_only || src_in_image(src, numImageVisuals, pImageVisuals))
808b3307321Smrg			{
809b3307321Smrg			    subtr_rect_from_image_region( new_reg, src->x_vis,
810b3307321Smrg					  src->y_vis, src->width, src->height);
811b3307321Smrg			}
812b3307321Smrg		    }
813b3307321Smrg		}
814b3307321Smrg		XIntersectRegion( bbox_region, new_reg->visible_region,
815b3307321Smrg				  new_reg->visible_region);
816b3307321Smrg		if (! XEmptyRegion( new_reg->visible_region)) {
817b3307321Smrg		    add_to_list( image_regions, new_reg);
818b3307321Smrg		    if (new_reg->vis != DefaultVisualOfScreen( win_attrs.screen) ||
819b3307321Smrg			new_reg->cmap != DefaultColormapOfScreen(
820b3307321Smrg							    win_attrs.screen)) {
821b3307321Smrg			*hasNonDefault = True;
822b3307321Smrg		    }
823b3307321Smrg		}
824b3307321Smrg		else {
825b3307321Smrg		    XDestroyRegion( new_reg->visible_region);
826b3307321Smrg		    free( (void *) new_reg);
827b3307321Smrg		}
828b3307321Smrg	    }
829b3307321Smrg	} else *allImage = 0;
830b3307321Smrg    }
831b3307321Smrg    delete_list( &image_wins, True);
832b3307321Smrg    XDestroyRegion( bbox_region);
833b3307321Smrg    return image_regions;
834b3307321Smrg}
835b3307321Smrg/** ------------------------------------------------------------------------
836b3307321Smrg	Destructor called from destroy_region_list().
837b3307321Smrg    ------------------------------------------------------------------------ **/
8385e358ecaSmrgstatic void destroy_image_region(image_region_type *image_region)
839b3307321Smrg{
840b3307321Smrg    XDestroyRegion( image_region->visible_region);
841b3307321Smrg    free( (void *) image_region);
842b3307321Smrg}
843b3307321Smrg
844b3307321Smrg/** ------------------------------------------------------------------------
845b3307321Smrg	Destroys the region list, destroying all the regions contained in it.
846b3307321Smrg    ------------------------------------------------------------------------ **/
8475e358ecaSmrgstatic void destroy_region_list(list_ptr rlist)
848b3307321Smrg{
849b3307321Smrg    delete_list_destroying( rlist, (DESTRUCT_FUNC_PTR)destroy_image_region);
850b3307321Smrg}
851b3307321Smrg
852b3307321Smrg
853b3307321Smrg/** ------------------------------------------------------------------------
854b3307321Smrg	Subtracts the specified rectangle from the region in image_region.
855b3307321Smrg	First converts the rectangle to a region of its own, since X
856b3307321Smrg	only provides a way to subtract one region from another, not a
857b3307321Smrg	rectangle from a region.
858b3307321Smrg    ------------------------------------------------------------------------ **/
8595e358ecaSmrgstatic void subtr_rect_from_image_region(image_region_type *image_region,
8605e358ecaSmrg					 int x, int y, int width, int height)
861b3307321Smrg{
862b3307321Smrg    XRectangle rect;
863b3307321Smrg    Region rect_region;
864b3307321Smrg
865b3307321Smrg    rect_region = XCreateRegion();
866b3307321Smrg    rect.x = x;
867b3307321Smrg    rect.y = y;
868b3307321Smrg    rect.width = width;
869b3307321Smrg    rect.height = height;
870b3307321Smrg    XUnionRectWithRegion( &rect, rect_region, rect_region);
871b3307321Smrg    XSubtractRegion( image_region->visible_region, rect_region,
872b3307321Smrg		     image_region->visible_region);
873b3307321Smrg    XDestroyRegion( rect_region);
874b3307321Smrg}
875b3307321Smrg
876b3307321Smrg
877b3307321Smrg/** ------------------------------------------------------------------------
878b3307321Smrg	Adds the specified rectangle to the region in image_region.
879b3307321Smrg    ------------------------------------------------------------------------ **/
8805e358ecaSmrgstatic void add_rect_to_image_region(image_region_type *image_region,
8815e358ecaSmrg				     int x, int y, int width, int height)
882b3307321Smrg{
883b3307321Smrg    XRectangle rect;
884b3307321Smrg
885b3307321Smrg    rect.x = x;
886b3307321Smrg    rect.y = y;
887b3307321Smrg    rect.width = width;
888b3307321Smrg    rect.height = height;
889b3307321Smrg    XUnionRectWithRegion( &rect, image_region->visible_region,
890b3307321Smrg			  image_region->visible_region);
891b3307321Smrg}
892b3307321Smrg
893b3307321Smrg
894b3307321Smrg/** ------------------------------------------------------------------------
895b3307321Smrg	Returns TRUE if the given src's visual is already represented in
896b3307321Smrg	the image_regions list, FALSE otherwise.
897b3307321Smrg    ------------------------------------------------------------------------ **/
8985e358ecaSmrgstatic int src_in_region_list(image_win_type *src, list_ptr image_regions)
899b3307321Smrg{
900b3307321Smrg    image_region_type	*ir;
901b3307321Smrg
902b3307321Smrg    for (ir = (image_region_type *) first_in_list( image_regions); ir;
903b3307321Smrg	 ir = (image_region_type *) next_in_list( image_regions)) {
904b3307321Smrg	if (SAME_REGIONS( ir, src)) {
905b3307321Smrg
906b3307321Smrg	    return 1;
907b3307321Smrg	}
908b3307321Smrg    }
909b3307321Smrg
910b3307321Smrg    return 0;
911b3307321Smrg}
912b3307321Smrg
913b3307321Smrg
914b3307321Smrg/** ------------------------------------------------------------------------
915b3307321Smrg	Makes a new entry in image_wins with the given fields filled in.
916b3307321Smrg    ------------------------------------------------------------------------ **/
9175e358ecaSmrgstatic void add_window_to_list(list_ptr image_wins, Window w,
9185e358ecaSmrg			       int xrr, int yrr, int x_vis, int y_vis,
9195e358ecaSmrg			       int width, int height, int border_width,
9205e358ecaSmrg			       Visual *vis, Colormap cmap, Window parent)
921b3307321Smrg{
922b3307321Smrg    image_win_type	*new_src;
923b3307321Smrg
924b3307321Smrg    if ((new_src = (image_win_type *) malloc( sizeof( image_win_type))) == NULL)
925b3307321Smrg
926b3307321Smrg	return;
927b3307321Smrg
928b3307321Smrg    new_src->win = w;
929b3307321Smrg    new_src->x_rootrel = xrr;
930b3307321Smrg    new_src->y_rootrel = yrr;
931b3307321Smrg    new_src->x_vis = x_vis;
932b3307321Smrg    new_src->y_vis = y_vis;
933b3307321Smrg    new_src->width = width;
934b3307321Smrg    new_src->height = height;
935b3307321Smrg    new_src->border_width = border_width;
936b3307321Smrg    new_src->vis = vis;
937b3307321Smrg    new_src->cmap = cmap;
938b3307321Smrg    new_src->parent = parent;
939b3307321Smrg    add_to_list( image_wins, new_src);
940b3307321Smrg}
941b3307321Smrg
942b3307321Smrg/** ------------------------------------------------------------------------
943b3307321Smrg	Returns TRUE if the given src's visual is in the image planes,
944b3307321Smrg	FALSE otherwise.
945b3307321Smrg    ------------------------------------------------------------------------ **/
9465e358ecaSmrgstatic int src_in_image(image_win_type *src, int numImageVisuals,
9475e358ecaSmrg			XVisualInfo **pImageVisuals)
948b3307321Smrg{
949b3307321Smrg    int 		i;
950b3307321Smrg
951b3307321Smrg    for (i = 0 ; i < numImageVisuals ; i++)
952b3307321Smrg    {
953b3307321Smrg	if (pImageVisuals[i]->visual == src->vis)
954b3307321Smrg	    return 1;
955b3307321Smrg    }
956b3307321Smrg    return 0;
957b3307321Smrg}
958b3307321Smrg
959b3307321Smrg
960b3307321Smrg/** ------------------------------------------------------------------------
961b3307321Smrg	Returns TRUE if the given src's visual is in the overlay planes
962b3307321Smrg	and transparency is possible, FALSE otherwise.
963b3307321Smrg    ------------------------------------------------------------------------ **/
9645e358ecaSmrgstatic int src_in_overlay(image_region_type *src, int numOverlayVisuals,
9655e358ecaSmrg			  OverlayInfo *pOverlayVisuals,
9665e358ecaSmrg			  int *transparentColor, int *transparentType)
967b3307321Smrg{
968b3307321Smrg    int 		i;
969b3307321Smrg
970b3307321Smrg    for (i = 0 ; i < numOverlayVisuals ; i++)
971b3307321Smrg    {
972b3307321Smrg	if (((pOverlayVisuals[i].pOverlayVisualInfo)->visual == src->vis)
973b3307321Smrg		&& (pOverlayVisuals[i].transparentType != None))
974b3307321Smrg	{
975b3307321Smrg	    *transparentColor = pOverlayVisuals[i].value;
976b3307321Smrg	    *transparentType = pOverlayVisuals[i].transparentType;
977b3307321Smrg	    return 1;
978b3307321Smrg	}
979b3307321Smrg
980b3307321Smrg	else {
981b3307321Smrg	}
982b3307321Smrg
983b3307321Smrg    }
984b3307321Smrg    return 0;
985b3307321Smrg}
986b3307321Smrg
987b3307321Smrg
988b3307321Smrg/********************** from wsutils.c ******************************/
989b3307321Smrg
990b3307321Smrg/******************************************************************************
991b3307321Smrg *
992b3307321Smrg * This file contains a set of example utility procedures; procedures that can
993b3307321Smrg * help a "window-smart" Starbase or PHIGS program determine information about
994b3307321Smrg * a device, and create image and overlay plane windows.  To use these
995b3307321Smrg * utilities, #include "wsutils.h" and compile this file and link the results
996b3307321Smrg * with your program.
997b3307321Smrg *
998b3307321Smrg ******************************************************************************/
999b3307321Smrg
1000b3307321Smrg
1001b3307321Smrg
1002b3307321Smrg#define STATIC_GRAY	0x01
1003b3307321Smrg#define GRAY_SCALE	0x02
1004b3307321Smrg#define PSEUDO_COLOR	0x04
1005b3307321Smrg#define TRUE_COLOR	0x10
1006b3307321Smrg#define DIRECT_COLOR	0x11
1007b3307321Smrg
1008b3307321Smrg
1009b3307321Smrgstatic int	weCreateServerOverlayVisualsProperty = False;
1010b3307321Smrg
1011b3307321Smrg
1012b3307321Smrg/******************************************************************************
1013b3307321Smrg *
1014b3307321Smrg * GetXVisualInfo()
1015b3307321Smrg *
1016b3307321Smrg * This routine takes an X11 Display, screen number, and returns whether the
1017b3307321Smrg * screen supports transparent overlays and three arrays:
1018b3307321Smrg *
1019b3307321Smrg *	1) All of the XVisualInfo struct's for the screen.
1020b3307321Smrg *	2) All of the OverlayInfo struct's for the screen.
1021b3307321Smrg *	3) An array of pointers to the screen's image plane XVisualInfo
1022b3307321Smrg *	   structs.
1023b3307321Smrg *
1024b3307321Smrg * The code below obtains the array of all the screen's visuals, and obtains
1025b3307321Smrg * the array of all the screen's overlay visual information.  It then processes
1026b3307321Smrg * the array of the screen's visuals, determining whether the visual is an
1027b3307321Smrg * overlay or image visual.
1028b3307321Smrg *
1029b3307321Smrg * If the routine sucessfully obtained the visual information, it returns zero.
1030b3307321Smrg * If the routine didn't obtain the visual information, it returns non-zero.
1031b3307321Smrg *
1032b3307321Smrg ******************************************************************************/
1033b3307321Smrg
10345e358ecaSmrgint GetXVisualInfo(/* Which X server (aka "display"). */
10355e358ecaSmrg		   Display *display,
10365e358ecaSmrg		   /* Which screen of the "display". */
10375e358ecaSmrg		   int screen,
10385e358ecaSmrg		   /* Non-zero if there's at least one overlay visual and
10395e358ecaSmrg		    * if at least one of those supports a transparent pixel. */
10405e358ecaSmrg		   int *transparentOverlays,
10415e358ecaSmrg		   /* Number of XVisualInfo struct's pointed to by pVisuals. */
10425e358ecaSmrg		   int *numVisuals,
10435e358ecaSmrg		   /* All of the device's visuals. */
10445e358ecaSmrg		   XVisualInfo **pVisuals,
10455e358ecaSmrg		   /* Number of OverlayInfo's pointed to by pOverlayVisuals.
10465e358ecaSmrg		    * If this number is zero, the device does not have
10475e358ecaSmrg		    * overlay planes. */
10485e358ecaSmrg		   int *numOverlayVisuals,
10495e358ecaSmrg		   /* The device's overlay plane visual information. */
10505e358ecaSmrg		   OverlayInfo	**pOverlayVisuals,
10515e358ecaSmrg		   /* Number of XVisualInfo's pointed to by pImageVisuals. */
10525e358ecaSmrg		   int *numImageVisuals,
10535e358ecaSmrg		   /* The device's image visuals. */
10545e358ecaSmrg		   XVisualInfo ***pImageVisuals)
1055b3307321Smrg{
1056b3307321Smrg    XVisualInfo	getVisInfo;		/* Paramters of XGetVisualInfo */
1057b3307321Smrg    int		mask;
1058b3307321Smrg    XVisualInfo	*pVis, **pIVis;		/* Faster, local copies */
1059b3307321Smrg    OverlayInfo	*pOVis;
1060b3307321Smrg    OverlayVisualPropertyRec	*pOOldVis;
1061b3307321Smrg    int		nVisuals, nOVisuals;
1062b3307321Smrg    Atom	overlayVisualsAtom;	/* Parameters for XGetWindowProperty */
1063b3307321Smrg    Atom	actualType;
1064b3307321Smrg    unsigned long numLongs, bytesAfter;
1065b3307321Smrg    int		actualFormat;
1066b3307321Smrg    int		nImageVisualsAlloced;	/* Values to process the XVisualInfo */
1067b3307321Smrg    int		imageVisual;		/* array */
1068b3307321Smrg
1069b3307321Smrg
1070b3307321Smrg    /* First, get the list of visuals for this screen. */
1071b3307321Smrg    getVisInfo.screen = screen;
1072b3307321Smrg    mask = VisualScreenMask;
1073b3307321Smrg
1074b3307321Smrg    *pVisuals = XGetVisualInfo(display, mask, &getVisInfo, numVisuals);
1075b3307321Smrg    if ((nVisuals = *numVisuals) <= 0)
1076b3307321Smrg    {
1077b3307321Smrg	/* Return that the information wasn't sucessfully obtained: */
1078b3307321Smrg	return(1);
1079b3307321Smrg    }
1080b3307321Smrg    pVis = *pVisuals;
1081b3307321Smrg
1082b3307321Smrg
1083b3307321Smrg    /* Now, get the overlay visual information for this screen.  To obtain
1084b3307321Smrg     * this information, get the SERVER_OVERLAY_VISUALS property.
1085b3307321Smrg     */
1086b3307321Smrg    overlayVisualsAtom = XInternAtom(display, "SERVER_OVERLAY_VISUALS", True);
1087b3307321Smrg    if (overlayVisualsAtom != None)
1088b3307321Smrg    {
1089b3307321Smrg	/* Since the Atom exists, we can request the property's contents.  The
1090b3307321Smrg	 * do-while loop makes sure we get the entire list from the X server.
1091b3307321Smrg	 */
1092b3307321Smrg	bytesAfter = 0;
1093b3307321Smrg	numLongs = sizeof(OverlayVisualPropertyRec) / 4;
1094b3307321Smrg	do
1095b3307321Smrg	{
1096b3307321Smrg	    numLongs += bytesAfter * 4;
1097b3307321Smrg	    XGetWindowProperty(display, RootWindow(display, screen),
1098b3307321Smrg			       overlayVisualsAtom, 0, numLongs, False,
1099b3307321Smrg			       overlayVisualsAtom, &actualType, &actualFormat,
1100b3307321Smrg			       &numLongs, &bytesAfter, (unsigned char**) pOverlayVisuals);
1101b3307321Smrg	} while (bytesAfter > 0);
1102b3307321Smrg
1103b3307321Smrg
1104b3307321Smrg	/* Calculate the number of overlay visuals in the list. */
1105b3307321Smrg	*numOverlayVisuals = numLongs / (sizeof(OverlayVisualPropertyRec) / 4);
1106b3307321Smrg    }
1107b3307321Smrg    else
1108b3307321Smrg    {
1109b3307321Smrg	/* This screen doesn't have overlay planes. */
1110b3307321Smrg	*numOverlayVisuals = 0;
1111b3307321Smrg	*pOverlayVisuals = NULL;
1112b3307321Smrg	*transparentOverlays = 0;
1113b3307321Smrg    }
1114b3307321Smrg
1115b3307321Smrg
1116b3307321Smrg    /* Process the pVisuals array. */
1117b3307321Smrg    *numImageVisuals = 0;
1118b3307321Smrg    nImageVisualsAlloced = 1;
1119b3307321Smrg    pIVis = *pImageVisuals = (XVisualInfo **) malloc(sizeof(XVisualInfo *));
1120b3307321Smrg    while (--nVisuals >= 0)
1121b3307321Smrg    {
1122b3307321Smrg	nOVisuals = *numOverlayVisuals;
1123b3307321Smrg	pOVis = *pOverlayVisuals;
1124b3307321Smrg	imageVisual = True;
1125b3307321Smrg	while (--nOVisuals >= 0)
1126b3307321Smrg	{
1127b3307321Smrg	    pOOldVis = (OverlayVisualPropertyRec *) pOVis;
1128b3307321Smrg	    if (pVis->visualid == pOOldVis->visualID)
1129b3307321Smrg	    {
1130b3307321Smrg		imageVisual = False;
1131b3307321Smrg		pOVis->pOverlayVisualInfo = pVis;
1132b3307321Smrg		if (pOVis->transparentType == TransparentPixel)
1133b3307321Smrg		    *transparentOverlays = 1;
1134b3307321Smrg	    }
1135b3307321Smrg	    pOVis++;
1136b3307321Smrg	}
1137b3307321Smrg	if (imageVisual)
1138b3307321Smrg	{
1139b3307321Smrg	    if ((*numImageVisuals += 1) > nImageVisualsAlloced)
1140b3307321Smrg	    {
1141b3307321Smrg		nImageVisualsAlloced++;
1142b3307321Smrg		*pImageVisuals = (XVisualInfo **)
1143b3307321Smrg		    realloc(*pImageVisuals, (nImageVisualsAlloced * sizeof(XVisualInfo *)));
1144b3307321Smrg		pIVis = *pImageVisuals + (*numImageVisuals - 1);
1145b3307321Smrg	    }
1146b3307321Smrg	    *pIVis++ = pVis;
1147b3307321Smrg	}
1148b3307321Smrg	pVis++;
1149b3307321Smrg    }
1150b3307321Smrg
1151b3307321Smrg
1152b3307321Smrg    /* Return that the information was sucessfully obtained: */
1153b3307321Smrg    return(0);
1154b3307321Smrg
1155b3307321Smrg} /* GetXVisualInfo() */
1156b3307321Smrg
1157b3307321Smrg
1158b3307321Smrg/******************************************************************************
1159b3307321Smrg *
1160b3307321Smrg * FreeXVisualInfo()
1161b3307321Smrg *
1162b3307321Smrg * This routine frees the data that was allocated by GetXVisualInfo().
1163b3307321Smrg *
1164b3307321Smrg ******************************************************************************/
1165b3307321Smrg
11665e358ecaSmrgvoid FreeXVisualInfo(XVisualInfo *pVisuals, OverlayInfo *pOverlayVisuals,
11675e358ecaSmrg		     XVisualInfo **pImageVisuals)
1168b3307321Smrg{
1169b3307321Smrg    XFree(pVisuals);
1170b3307321Smrg    if (weCreateServerOverlayVisualsProperty)
1171b3307321Smrg	free(pOverlayVisuals);
1172b3307321Smrg    else
1173b3307321Smrg	XFree(pOverlayVisuals);
1174b3307321Smrg    free(pImageVisuals);
1175b3307321Smrg
1176b3307321Smrg} /* FreeXVisualInfo() */
1177