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