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