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 image_region_type* reg; 399 int32_t rect; 400 401 ximage = XCreateImage(disp,fakeVis,(uint32_t) depth,format,0,NULL, 402 (uint32_t)width,(uint32_t)height,8,0); 403 404 ximage->data = calloc(ximage->bytes_per_line*height*((format==ZPixmap)? 1 : depth), sizeof(char)); 405 ximage->bits_per_pixel = depth; /** Valid only if format is ZPixmap ***/ 406 407 for (reg = (image_region_type *) first_in_list( regions); reg; 408 reg = (image_region_type *) next_in_list( regions)) 409 { 410 struct my_XRegion *vis_reg = (struct my_XRegion *)(reg->visible_region); 411 for (rect = 0; rect < vis_reg->numRects; rect++) 412 { 413 /** ------------------------------------------------------------------------ 414 Intersect bbox with visible part of region giving src rect & output 415 location. Width is the min right side minus the max left side. 416 Similar for height. Offset src rect so x,y are relative to 417 origin of win, not the root-relative visible rect of win. 418 ------------------------------------------------------------------------ **/ 419 int32_t srcRect_width = MIN( vis_reg->rects[rect].x2, bbox.width + bbox.x) 420 - MAX( vis_reg->rects[rect].x1, bbox.x); 421 422 int32_t srcRect_height = MIN( vis_reg->rects[rect].y2, bbox.height + bbox.y) 423 - MAX( vis_reg->rects[rect].y1, bbox.y); 424 425 int32_t diff = bbox.x - vis_reg->rects[rect].x1; 426 int32_t srcRect_x = MAX( 0, diff) + (vis_reg->rects[rect].x1 - reg->x_rootrel - reg->border); 427 int32_t dst_x = MAX( 0, -diff) ; 428 429 diff = bbox.y - vis_reg->rects[rect].y1; 430 int32_t srcRect_y = MAX( 0, diff) + (vis_reg->rects[rect].y1 - reg->y_rootrel - reg->border); 431 int32_t dst_y = MAX( 0, -diff) ; 432 XImage* reg_image = XGetImage(disp,reg->win,srcRect_x,srcRect_y, 433 (uint32_t) srcRect_width, (uint32_t) srcRect_height,AllPlanes,format) ; 434 435 if (reg_image) { 436 TransferImage(disp,reg_image,srcRect_width, 437 srcRect_height,reg,ximage,dst_x,dst_y) ; 438 XDestroyImage(reg_image); 439 } 440 } 441 } 442 return ximage ; 443 } 444 445 446 /** ------------------------------------------------------------------------ 447 ------------------------------------------------------------------------ **/ 448 449 XImage *ReadAreaToImage(disp, srcRootWinid, x, y, width, height, 450 numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals,numImageVisuals, 451 pImageVisuals,vis_regions,vis_image_regions,format,allImage) 452 Display *disp; 453 Window srcRootWinid; /* root win on which grab was done */ 454 int32_t x; /* root rel UL corner of bounding box of grab */ 455 int32_t y; 456 uint32_t width; /* size of bounding box of grab */ 457 uint32_t height; 458 /** int32_t transparentOverlays; ***/ 459 int32_t numVisuals; 460 XVisualInfo *pVisuals; 461 int32_t numOverlayVisuals; 462 OverlayInfo *pOverlayVisuals; 463 int32_t numImageVisuals; 464 XVisualInfo **pImageVisuals; 465 list_ptr vis_regions; /* list of regions to read from */ 466 list_ptr vis_image_regions ;/* list of regions to read from */ 467 int32_t format; 468 int32_t allImage ; 469 { 470 image_region_type *reg; 471 XRectangle bbox; /* bounding box of grabbed area */ 472 int32_t depth ; 473 XImage *ximage, *ximage_ipm ; 474 Visual fakeVis ; 475 int32_t x1, y1; 476 XImage *image; 477 unsigned char *pmData , *ipmData ; 478 int32_t transparentColor, transparentType; 479 int32_t srcRect_x,srcRect_y,srcRect_width,srcRect_height ; 480 int32_t diff ; 481 int32_t dst_x, dst_y; /* where in pixmap to write (UL) */ 482 int32_t pixel; 483 484 bbox.x = (short) x; /* init X rect for bounding box */ 485 bbox.y = (short) y; 486 bbox.width = (unsigned short) width; 487 bbox.height = (unsigned short) height; 488 ximage_ipm = NULL; 489 490 491 initFakeVisual(&fakeVis) ; 492 493 depth = 24 ; 494 ximage = ReadRegionsInList(disp,&fakeVis,depth,format, 495 (int32_t) width, (int32_t) height, bbox,vis_regions) ; 496 497 pmData = (unsigned char *)ximage -> data ; 498 499 /* if transparency possible do it again, but this time for image planes only */ 500 if (vis_image_regions && (vis_image_regions->next) && !allImage) 501 { 502 ximage_ipm = ReadRegionsInList(disp,&fakeVis,depth,format, 503 (int32_t) width, (int32_t) height,bbox,vis_image_regions) ; 504 ipmData = (unsigned char *)ximage_ipm -> data ; 505 } 506 /* Now tranverse the overlay visual windows and test for transparency index. */ 507 /* If you find one, subsitute the value from the matching image plane pixmap. */ 508 509 for (reg = (image_region_type *) first_in_list( vis_regions); reg; 510 reg = (image_region_type *) next_in_list( vis_regions)) 511 { 512 513 if (src_in_overlay( reg, numOverlayVisuals, pOverlayVisuals, 514 &transparentColor, &transparentType)) 515 { 516 int32_t test = 0 ; 517 srcRect_width = MIN( reg->width + reg->x_vis, bbox.width + bbox.x) 518 - MAX( reg->x_vis, bbox.x); 519 srcRect_height = MIN( reg->height + reg->y_vis, bbox.height 520 + bbox.y) - MAX( reg->y_vis, bbox.y); 521 diff = bbox.x - reg->x_vis; 522 srcRect_x = MAX( 0, diff) + (reg->x_vis - reg->x_rootrel - reg->border); 523 dst_x = MAX( 0, -diff) ; 524 diff = bbox.y - reg->y_vis; 525 srcRect_y = MAX( 0, diff) + (reg->y_vis - reg->y_rootrel - reg->border); 526 dst_y = MAX( 0, -diff) ; 527 /* let's test some pixels for transparency */ 528 image = XGetImage(disp, reg->win, srcRect_x, srcRect_y, 529 (uint32_t) srcRect_width, (uint32_t) srcRect_height, 530 0xffffffff, ZPixmap); 531 532 /* let's assume byte per pixel for overlay image for now */ 533 if ((image->depth == 8) && (transparentType == TransparentPixel)) 534 { 535 unsigned char *pixel_ptr; 536 unsigned char *start_of_line = (unsigned char *) image->data; 537 538 for (y1 = 0; y1 < srcRect_height; y1++) { 539 pixel_ptr = start_of_line; 540 for (x1 = 0; x1 < srcRect_width; x1++) 541 { 542 if (*pixel_ptr++ == transparentColor) 543 { 544 /* 545 *pmData++ = *ipmData++; 546 *pmData++ = *ipmData++; 547 *pmData++ = *ipmData++; 548 */ 549 pixel = (int32_t) XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ; 550 XPutPixel(ximage,dst_x+x1, dst_y+y1,(unsigned long)pixel); 551 552 if(!test){ 553 test = 1 ; 554 } 555 } 556 /* 557 else { 558 pmData +=3; 559 ipmData +=3; 560 } 561 */ 562 } 563 start_of_line += image->bytes_per_line; 564 } 565 } else { 566 if (transparentType == TransparentPixel) { 567 for (y1 = 0; y1 < srcRect_height; y1++) { 568 for (x1 = 0; x1 < srcRect_width; x1++) 569 { 570 int32_t pixel_value = (int32_t) XGetPixel(image, x1, y1); 571 if (pixel_value == transparentColor) 572 { 573 /* 574 *pmData++ = *ipmData++; 575 *pmData++ = *ipmData++; 576 *pmData++ = *ipmData++; 577 */ 578 pixel = (int32_t) XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ; 579 XPutPixel(ximage,dst_x+x1, dst_y+y1,(unsigned long)pixel); 580 if(!test){ 581 test = 1 ; 582 } 583 } 584 /* 585 else { 586 pmData +=3; 587 ipmData +=3; 588 } 589 */ 590 } 591 } 592 } else { 593 for (y1 = 0; y1 < srcRect_height; y1++) { 594 for (x1 = 0; x1 < srcRect_width; x1++) 595 { 596 int32_t pixel_value = (int32_t) XGetPixel(image, x1, y1); 597 if (pixel_value & transparentColor) 598 { 599 /* 600 *pmData++ = *ipmData++; 601 *pmData++ = *ipmData++; 602 *pmData++ = *ipmData++; 603 */ 604 pixel = (int32_t) XGetPixel(ximage_ipm,dst_x+x1, 605 dst_y+y1) ; 606 XPutPixel(ximage,dst_x+x1, dst_y+y1,(unsigned long)pixel); 607 if(!test){ 608 test = 1 ; 609 } 610 } 611 /* 612 else { 613 pmData +=3; 614 ipmData +=3; 615 } 616 */ 617 } 618 } 619 } 620 } 621 XDestroyImage (image); 622 } /* end of src_in_overlay */ 623 } /** end transparency **/ 624 if (ximage_ipm != NULL) { 625 XDestroyImage(ximage_ipm); 626 } 627 destroy_region_list( vis_regions); 628 if (vis_image_regions) destroy_region_list( vis_image_regions ); 629 FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals); 630 XSync(disp, 0); 631 632 return ximage; 633 } 634 635 /** ------------------------------------------------------------------------ 636 Creates a list of the subwindows of a given window which have a 637 different visual than their parents. The function is recursive. 638 This list is used in make_region_list(), which coalesces the 639 windows with the same visual into a region. 640 image_wins must point to an existing list struct that's already 641 been zeroed (zero_list()). 642 ------------------------------------------------------------------------ **/ 643 static void make_src_list( disp, image_wins, bbox, curr, x_rootrel, y_rootrel, 644 curr_attrs, pclip) 645 Display *disp; 646 list_ptr image_wins; 647 XRectangle *bbox; /* bnding box of area we want */ 648 Window curr; 649 int32_t x_rootrel; /* pos of curr WRT root */ 650 int32_t y_rootrel; 651 XWindowAttributes *curr_attrs; 652 XRectangle *pclip; /* visible part of curr, not */ 653 /* obscurred by ancestors */ 654 { 655 XWindowAttributes child_attrs; 656 Window root, parent, *child; /* variables for XQueryTree() */ 657 Window *save_child_list; /* variables for XQueryTree() */ 658 uint32_t nchild; /* variables for XQueryTree() */ 659 XRectangle child_clip; /* vis part of child */ 660 int32_t curr_clipX, curr_clipY, curr_clipRt, curr_clipBt; 661 662 /* check that win is mapped & not outside bounding box */ 663 if (curr_attrs->map_state == IsViewable && 664 curr_attrs->class == InputOutput && 665 !( pclip->x >= (bbox->x + bbox->width) || 666 pclip->y >= (bbox->y + bbox->height) || 667 (pclip->x + pclip->width) <= bbox->x || 668 (pclip->y + pclip->height) <= bbox->y)) { 669 670 XQueryTree( disp, curr, &root, &parent, &child, &nchild ); 671 save_child_list = child; /* so we can free list when we're done */ 672 add_window_to_list( image_wins, curr, x_rootrel, y_rootrel, 673 (int32_t) pclip->x, (int32_t) pclip->y, 674 (int32_t) pclip->width, (int32_t) pclip->height, 675 curr_attrs->border_width,curr_attrs->visual, 676 curr_attrs->colormap, parent); 677 678 679 /** ------------------------------------------------------------------------ 680 set RR coords of right (Rt), left (X), bottom (Bt) and top (Y) 681 of rect we clip all children by. This is our own clip rect (pclip) 682 inflicted on us by our parent plus our own borders. Within the 683 child loop, we figure the clip rect for each child by adding in 684 it's rectangle (not taking into account the child's borders). 685 ------------------------------------------------------------------------ **/ 686 curr_clipX = MAX( pclip->x, x_rootrel + curr_attrs->border_width); 687 curr_clipY = MAX( pclip->y, y_rootrel + curr_attrs->border_width); 688 curr_clipRt = MIN(pclip->x + pclip->width, 689 x_rootrel + curr_attrs->width + 2 * curr_attrs->border_width); 690 691 curr_clipBt = MIN(pclip->y + pclip->height, 692 y_rootrel + curr_attrs->height + 2 * curr_attrs->border_width); 693 694 695 while (nchild--) { 696 int32_t new_width, new_height; 697 int32_t child_xrr, child_yrr; /* root relative x & y of child */ 698 699 XGetWindowAttributes( disp, *child, &child_attrs); 700 701 /* intersect parent & child clip rects */ 702 child_xrr = x_rootrel + child_attrs.x + curr_attrs->border_width; 703 child_clip.x = (short) MAX( curr_clipX, child_xrr); 704 new_width = MIN(curr_clipRt, 705 child_xrr + child_attrs.width + 706 2 * child_attrs.border_width) - child_clip.x; 707 708 if (new_width >= 0) { 709 child_clip.width = (unsigned short) new_width; 710 711 child_yrr = y_rootrel + child_attrs.y + 712 curr_attrs->border_width; 713 child_clip.y = (short) MAX( curr_clipY, child_yrr); 714 new_height = MIN(curr_clipBt, 715 child_yrr + (int32_t) child_attrs.height + 716 2 * child_attrs.border_width) - child_clip.y; 717 718 if (new_height >= 0) { 719 child_clip.height = (unsigned short) new_height; 720 make_src_list( disp, image_wins, bbox, *child, 721 child_xrr, child_yrr, 722 &child_attrs, &child_clip); 723 } 724 } 725 child++; 726 } 727 XFree( save_child_list); 728 } 729 } 730 731 732 /** ------------------------------------------------------------------------ 733 This function creates a list of regions which tile a specified 734 window. Each region contains all visible portions of the window 735 which are drawn with the same visual. For example, if the 736 window consists of subwindows of two different visual types, 737 there will be two regions in the list. 738 Returns a pointer to the list. 739 ------------------------------------------------------------------------ **/ 740 static list_ptr make_region_list( disp, win, bbox, hasNonDefault, 741 numImageVisuals, pImageVisuals, allImage) 742 Display *disp; 743 Window win; 744 XRectangle *bbox; 745 int32_t *hasNonDefault; 746 int32_t numImageVisuals; 747 XVisualInfo **pImageVisuals; 748 int32_t *allImage; 749 { 750 XWindowAttributes win_attrs; 751 list image_wins; 752 list_ptr image_regions; 753 list_ptr srcs_left; 754 image_region_type *new_reg; 755 image_win_type *base_src, *src; 756 Region bbox_region = XCreateRegion(); 757 XRectangle clip; 758 int32_t image_only; 759 760 int32_t count=0 ; 761 762 *hasNonDefault = False; 763 XUnionRectWithRegion( bbox, bbox_region, bbox_region); 764 XGetWindowAttributes( disp, win, &win_attrs); 765 766 zero_list( &image_wins); 767 clip.x = 0; 768 clip.y = 0; 769 clip.width = (unsigned short) win_attrs.width; 770 clip.height = (unsigned short) win_attrs.height; 771 make_src_list( disp, &image_wins, bbox, win, 772 0 /* x_rootrel */, 0 /* y_rootrel */, &win_attrs, &clip); 773 774 image_regions = new_list(); 775 image_only = (*allImage) ? True:False; 776 777 for (base_src = (image_win_type *) first_in_list( &image_wins); base_src; 778 base_src = (image_win_type *) next_in_list( &image_wins)) 779 { 780 /* test for image visual */ 781 if (!image_only || src_in_image(base_src, numImageVisuals, pImageVisuals)) 782 { 783 /* find a window whose visual hasn't been put in list yet */ 784 if (!src_in_region_list( base_src, image_regions)) 785 { 786 if (! (new_reg = (image_region_type *) 787 malloc( sizeof( image_region_type)))) { 788 return (list_ptr) NULL; 789 } 790 count++; 791 792 new_reg->visible_region = XCreateRegion(); 793 new_reg->win = base_src->win; 794 new_reg->vis = base_src->vis; 795 new_reg->cmap = base_src->cmap; 796 new_reg->x_rootrel = base_src->x_rootrel; 797 new_reg->y_rootrel = base_src->y_rootrel; 798 new_reg->x_vis = base_src->x_vis; 799 new_reg->y_vis = base_src->y_vis; 800 new_reg->width = base_src->width; 801 new_reg->height = base_src->height; 802 new_reg->border = base_src->border_width; 803 804 srcs_left = (list_ptr) dup_list_head( &image_wins, START_AT_CURR); 805 for (src = (image_win_type *) first_in_list( srcs_left); src; 806 src = (image_win_type *) next_in_list( srcs_left)) { 807 if (SAME_REGIONS( base_src, src)) { 808 add_rect_to_image_region( new_reg, src->x_vis, src->y_vis, 809 src->width, src->height); 810 } 811 else { 812 if (!image_only || src_in_image(src, numImageVisuals, pImageVisuals)) 813 { 814 subtr_rect_from_image_region( new_reg, src->x_vis, 815 src->y_vis, src->width, src->height); 816 } 817 } 818 } 819 XIntersectRegion( bbox_region, new_reg->visible_region, 820 new_reg->visible_region); 821 if (! XEmptyRegion( new_reg->visible_region)) { 822 add_to_list( image_regions, new_reg); 823 if (new_reg->vis != DefaultVisualOfScreen( win_attrs.screen) || 824 new_reg->cmap != DefaultColormapOfScreen( 825 win_attrs.screen)) { 826 *hasNonDefault = True; 827 } 828 } 829 else { 830 XDestroyRegion( new_reg->visible_region); 831 free( (void *) new_reg); 832 } 833 } 834 } else *allImage = 0; 835 } 836 delete_list( &image_wins, True); 837 XDestroyRegion( bbox_region); 838 return image_regions; 839 } 840 /** ------------------------------------------------------------------------ 841 Destructor called from destroy_region_list(). 842 ------------------------------------------------------------------------ **/ 843 void destroy_image_region( image_region) 844 image_region_type *image_region; 845 { 846 XDestroyRegion( image_region->visible_region); 847 free( (void *) image_region); 848 } 849 850 /** ------------------------------------------------------------------------ 851 Destroys the region list, destroying all the regions contained in it. 852 ------------------------------------------------------------------------ **/ 853 static void destroy_region_list( rlist) 854 list_ptr rlist; 855 { 856 delete_list_destroying( rlist, (DESTRUCT_FUNC_PTR)destroy_image_region); 857 } 858 859 860 /** ------------------------------------------------------------------------ 861 Subtracts the specified rectangle from the region in image_region. 862 First converts the rectangle to a region of its own, since X 863 only provides a way to subtract one region from another, not a 864 rectangle from a region. 865 ------------------------------------------------------------------------ **/ 866 static void subtr_rect_from_image_region( image_region, x, y, width, height) 867 image_region_type *image_region; 868 int32_t x; 869 int32_t y; 870 int32_t width; 871 int32_t height; 872 { 873 XRectangle rect; 874 Region rect_region; 875 876 rect_region = XCreateRegion(); 877 rect.x = (short)x; 878 rect.y = (short)y; 879 rect.width = (unsigned short)width; 880 rect.height = (unsigned short)height; 881 XUnionRectWithRegion( &rect, rect_region, rect_region); 882 XSubtractRegion( image_region->visible_region, rect_region, 883 image_region->visible_region); 884 XDestroyRegion( rect_region); 885 } 886 887 888 /** ------------------------------------------------------------------------ 889 Adds the specified rectangle to the region in image_region. 890 ------------------------------------------------------------------------ **/ 891 static void add_rect_to_image_region( image_region, x, y, width, height) 892 image_region_type *image_region; 893 int32_t x; 894 int32_t y; 895 int32_t width; 896 int32_t height; 897 { 898 XRectangle rect; 899 900 rect.x = (short) x; 901 rect.y = (short) y; 902 rect.width = (unsigned short) width; 903 rect.height = (unsigned short) height; 904 XUnionRectWithRegion( &rect, image_region->visible_region, 905 image_region->visible_region); 906 } 907 908 909 /** ------------------------------------------------------------------------ 910 Returns TRUE if the given src's visual is already represented in 911 the image_regions list, FALSE otherwise. 912 ------------------------------------------------------------------------ **/ 913 static int32_t src_in_region_list( src, image_regions) 914 image_win_type *src; 915 list_ptr image_regions; 916 { 917 image_region_type *ir; 918 919 for (ir = (image_region_type *) first_in_list( image_regions); ir; 920 ir = (image_region_type *) next_in_list( image_regions)) { 921 if (SAME_REGIONS( ir, src)) { 922 923 return 1; 924 } 925 } 926 927 return 0; 928 } 929 930 931 /** ------------------------------------------------------------------------ 932 Makes a new entry in image_wins with the given fields filled in. 933 ------------------------------------------------------------------------ **/ 934 static void add_window_to_list( image_wins, w, xrr, yrr, x_vis, y_vis, 935 width, height, border_width,vis, cmap, parent) 936 list_ptr image_wins; 937 Window w; 938 int32_t xrr; 939 int32_t yrr; 940 int32_t x_vis; 941 int32_t y_vis; 942 int32_t width; 943 int32_t height; 944 int32_t border_width; 945 Visual *vis; 946 Colormap cmap; 947 Window parent; 948 { 949 image_win_type *new_src; 950 951 if ((new_src = (image_win_type *) malloc( sizeof( image_win_type))) == NULL) 952 953 return; 954 955 new_src->win = w; 956 new_src->x_rootrel = xrr; 957 new_src->y_rootrel = yrr; 958 new_src->x_vis = x_vis; 959 new_src->y_vis = y_vis; 960 new_src->width = width; 961 new_src->height = height; 962 new_src->border_width = border_width; 963 new_src->vis = vis; 964 new_src->cmap = cmap; 965 new_src->parent = parent; 966 add_to_list( image_wins, new_src); 967 } 968 969 /** ------------------------------------------------------------------------ 970 Returns TRUE if the given src's visual is in the image planes, 971 FALSE otherwise. 972 ------------------------------------------------------------------------ **/ 973 static int32_t src_in_image( src, numImageVisuals, pImageVisuals) 974 image_win_type *src; 975 int32_t numImageVisuals; 976 XVisualInfo **pImageVisuals; 977 { 978 int32_t i; 979 980 for (i = 0 ; i < numImageVisuals ; i++) 981 { 982 if (pImageVisuals[i]->visual == src->vis) 983 return 1; 984 } 985 return 0; 986 } 987 988 989 /** ------------------------------------------------------------------------ 990 Returns TRUE if the given src's visual is in the overlay planes 991 and transparency is possible, FALSE otherwise. 992 ------------------------------------------------------------------------ **/ 993 static int32_t src_in_overlay( src, numOverlayVisuals, pOverlayVisuals, 994 transparentColor, transparentType) 995 image_region_type *src; 996 int32_t numOverlayVisuals; 997 OverlayInfo *pOverlayVisuals; 998 int32_t *transparentColor; 999 int32_t *transparentType; 1000 { 1001 int32_t i; 1002 1003 for (i = 0 ; i < numOverlayVisuals ; i++) 1004 { 1005 if (((pOverlayVisuals[i].pOverlayVisualInfo)->visual == src->vis) 1006 && (pOverlayVisuals[i].transparentType != None)) 1007 { 1008 *transparentColor = pOverlayVisuals[i].value; 1009 *transparentType = pOverlayVisuals[i].transparentType; 1010 return 1; 1011 } 1012 1013 else { 1014 } 1015 1016 } 1017 return 0; 1018 } 1019 1020 1021 /********************** from wsutils.c ******************************/ 1022 1023 /****************************************************************************** 1024 * 1025 * This file contains a set of example utility procedures; procedures that can 1026 * help a "window-smart" Starbase or PHIGS program determine information about 1027 * a device, and create image and overlay plane windows. To use these 1028 * utilities, #include "wsutils.h" and compile this file and link the results 1029 * with your program. 1030 * 1031 ******************************************************************************/ 1032 1033 1034 1035 #define STATIC_GRAY 0x01 1036 #define GRAY_SCALE 0x02 1037 #define PSEUDO_COLOR 0x04 1038 #define TRUE_COLOR 0x10 1039 #define DIRECT_COLOR 0x11 1040 1041 1042 static int32_t weCreateServerOverlayVisualsProperty = False; 1043 1044 1045 /****************************************************************************** 1046 * 1047 * GetXVisualInfo() 1048 * 1049 * This routine takes an X11 Display, screen number, and returns whether the 1050 * screen supports transparent overlays and three arrays: 1051 * 1052 * 1) All of the XVisualInfo struct's for the screen. 1053 * 2) All of the OverlayInfo struct's for the screen. 1054 * 3) An array of pointers to the screen's image plane XVisualInfo 1055 * structs. 1056 * 1057 * The code below obtains the array of all the screen's visuals, and obtains 1058 * the array of all the screen's overlay visual information. It then processes 1059 * the array of the screen's visuals, determining whether the visual is an 1060 * overlay or image visual. 1061 * 1062 * If the routine sucessfully obtained the visual information, it returns zero. 1063 * If the routine didn't obtain the visual information, it returns non-zero. 1064 * 1065 ******************************************************************************/ 1066 1067 int32_t GetXVisualInfo(display, screen, transparentOverlays, 1068 numVisuals, pVisuals, 1069 numOverlayVisuals, pOverlayVisuals, 1070 numImageVisuals, pImageVisuals) 1071 1072 Display *display; /* Which X server (aka "display"). */ 1073 int32_t screen; /* Which screen of the "display". */ 1074 int32_t *transparentOverlays; /* Non-zero if there's at least one 1075 * overlay visual and if at least one 1076 * of those supports a transparent 1077 * pixel. */ 1078 int32_t *numVisuals; /* Number of XVisualInfo struct's 1079 * pointed to by pVisuals. */ 1080 XVisualInfo **pVisuals; /* All of the device's visuals. */ 1081 int32_t *numOverlayVisuals; /* Number of OverlayInfo's pointed 1082 * to by pOverlayVisuals. If this 1083 * number is zero, the device does 1084 * not have overlay planes. */ 1085 OverlayInfo **pOverlayVisuals; /* The device's overlay plane visual 1086 * information. */ 1087 int32_t *numImageVisuals; /* Number of XVisualInfo's pointed 1088 * to by pImageVisuals. */ 1089 XVisualInfo ***pImageVisuals; /* The device's image visuals. */ 1090 { 1091 XVisualInfo getVisInfo; /* Parameters of XGetVisualInfo */ 1092 int32_t mask; 1093 XVisualInfo *pVis, **pIVis; /* Faster, local copies */ 1094 OverlayInfo *pOVis; 1095 OverlayVisualPropertyRec *pOOldVis; 1096 int32_t nVisuals, nOVisuals; 1097 Atom overlayVisualsAtom; /* Parameters for XGetWindowProperty */ 1098 Atom actualType; 1099 unsigned long numLongs, bytesAfter; 1100 int32_t actualFormat; 1101 int32_t nImageVisualsAlloced; /* Values to process the XVisualInfo */ 1102 int32_t imageVisual; /* array */ 1103 1104 1105 /* First, get the list of visuals for this screen. */ 1106 getVisInfo.screen = screen; 1107 mask = VisualScreenMask; 1108 1109 *pVisuals = XGetVisualInfo(display, mask, &getVisInfo, numVisuals); 1110 if ((nVisuals = *numVisuals) <= 0) 1111 { 1112 /* Return that the information wasn't sucessfully obtained: */ 1113 return(1); 1114 } 1115 pVis = *pVisuals; 1116 1117 1118 /* Now, get the overlay visual information for this screen. To obtain 1119 * this information, get the SERVER_OVERLAY_VISUALS property. 1120 */ 1121 overlayVisualsAtom = XInternAtom(display, "SERVER_OVERLAY_VISUALS", True); 1122 if (overlayVisualsAtom != None) 1123 { 1124 /* Since the Atom exists, we can request the property's contents. The 1125 * do-while loop makes sure we get the entire list from the X server. 1126 */ 1127 bytesAfter = 0; 1128 numLongs = sizeof(OverlayVisualPropertyRec) / 4; 1129 do 1130 { 1131 numLongs += bytesAfter * 4; 1132 XGetWindowProperty(display, RootWindow(display, screen), 1133 overlayVisualsAtom, 0, numLongs, False, 1134 overlayVisualsAtom, &actualType, &actualFormat, 1135 &numLongs, &bytesAfter, (unsigned char**) pOverlayVisuals); 1136 } while (bytesAfter > 0); 1137 1138 1139 /* Calculate the number of overlay visuals in the list. */ 1140 /* *numOverlayVisuals = numLongs / (sizeof(OverlayVisualPropertyRec) / 4); */ 1141 *numOverlayVisuals = numLongs / (sizeof(OverlayVisualPropertyRec) / sizeof(long)); 1142 } 1143 else 1144 { 1145 /* This screen doesn't have overlay planes. */ 1146 *numOverlayVisuals = 0; 1147 *pOverlayVisuals = NULL; 1148 *transparentOverlays = 0; 1149 } 1150 1151 1152 /* Process the pVisuals array. */ 1153 *numImageVisuals = 0; 1154 nImageVisualsAlloced = 1; 1155 pIVis = *pImageVisuals = (XVisualInfo **) malloc(sizeof(XVisualInfo *)); 1156 while (--nVisuals >= 0) 1157 { 1158 nOVisuals = *numOverlayVisuals; 1159 pOVis = *pOverlayVisuals; 1160 imageVisual = True; 1161 while (--nOVisuals >= 0) 1162 { 1163 pOOldVis = (OverlayVisualPropertyRec *) pOVis; 1164 if (pVis->visualid == pOOldVis->visualID) 1165 { 1166 imageVisual = False; 1167 pOVis->pOverlayVisualInfo = pVis; 1168 if (pOVis->transparentType == TransparentPixel) 1169 *transparentOverlays = 1; 1170 } 1171 pOVis++; 1172 } 1173 if (imageVisual) 1174 { 1175 if ((*numImageVisuals += 1) > nImageVisualsAlloced) 1176 { 1177 nImageVisualsAlloced++; 1178 *pImageVisuals = (XVisualInfo **) 1179 realloc(*pImageVisuals, (nImageVisualsAlloced * sizeof(XVisualInfo *))); 1180 pIVis = *pImageVisuals + (*numImageVisuals - 1); 1181 } 1182 *pIVis++ = pVis; 1183 } 1184 pVis++; 1185 } 1186 1187 1188 /* Return that the information was sucessfully obtained: */ 1189 return(0); 1190 1191 } /* GetXVisualInfo() */ 1192 1193 1194 /****************************************************************************** 1195 * 1196 * FreeXVisualInfo() 1197 * 1198 * This routine frees the data that was allocated by GetXVisualInfo(). 1199 * 1200 ******************************************************************************/ 1201 1202 void FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals) 1203 1204 XVisualInfo *pVisuals; 1205 OverlayInfo *pOverlayVisuals; 1206 XVisualInfo **pImageVisuals; 1207 { 1208 XFree(pVisuals); 1209 if (weCreateServerOverlayVisualsProperty) 1210 free(pOverlayVisuals); 1211 else 1212 XFree(pOverlayVisuals); 1213 free(pImageVisuals); 1214 1215 } /* FreeXVisualInfo() */