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