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