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