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