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