blob: bb87b6b50006fd81d6f1c228c8b4765855933309 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Portions Copyright 1999-2004 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any 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
40Copyright (c) 1994 Hewlett-Packard Co.
41Copyright (c) 1996 X Consortium
42
43Permission is hereby granted, free of charge, to any person obtaining
44a copy of this software and associated documentation files (the
45"Software"), to deal in the Software without restriction, including
46without limitation the rights to use, copy, modify, merge, publish,
47distribute, sublicense, and sell copies of the Software, and to
48permit persons to whom the Software is furnished to do so, subject to
49the following conditions:
50
51The above copyright notice and this permission notice shall be included
52in all copies or substantial portions of the Software.
53
54THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
55OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
56MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
57IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
58OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
59ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
60OTHER DEALINGS IN THE SOFTWARE.
61
62Except as contained in this notice, the name of the X Consortium shall
63not be used in advertising or otherwise to promote the sale, use or
64other dealings in this Software without prior written authorization
65from 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
78static 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
83typedef struct {
84 short x1, x2, y1, y2;
85} myBox, myBOX, myBoxRec, *myBoxPtr;
86
87typedef 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 */
95typedef 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*/
109typedef 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/*
142extern list_ptr new_list();
143extern list_ptr dup_list_head();
144extern void * first_in_list();
145extern void * next_in_list();
146extern int32_t add_to_list();
147extern void zero_list();
148extern void delete_list();
149extern void delete_list_destroying();
150extern uint32_t list_length();
151*/
152
153/* Prototype Declarations for Static Functions */
154static void TransferImage(
155#if NeedFunctionPrototypes
156 Display *, XImage *,int32_t, int32_t , image_region_type*,
157 XImage *,int32_t ,int32_t
158#endif
159 );
160static XImage * ReadRegionsInList(
161#if NeedFunctionPrototypes
162 Display *, Visual *, int32_t ,int32_t ,int32_t ,
163 int32_t , XRectangle, list_ptr
164#endif
165 );
166
167static list_ptr make_region_list(
168#if NeedFunctionPrototypes
169 Display*, Window, XRectangle*,
170 int32_t*, int32_t, XVisualInfo**, int32_t *
171#endif
172 );
173
174static void destroy_region_list(
175#if NeedFunctionPrototypes
176 list_ptr
177#endif
178 ) ;
179static void subtr_rect_from_image_region(
180#if NeedFunctionPrototypes
181 image_region_type *, int32_t , int32_t , int32_t , int32_t
182#endif
183 );
184static 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 );
190static int32_t src_in_region_list(
191#if NeedFunctionPrototypes
192 image_win_type *, list_ptr
193#endif
194 );
195static 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 );
202static int32_t src_in_image(
203#if NeedFunctionPrototypes
204 image_win_type *, int32_t , XVisualInfo**
205#endif
206 );
207static 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
215void initFakeVisual(Vis)
216Visual *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
231int32_t
232GetMultiVisualRegions(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
293static void TransferImage(disp,reg_image,srcw,srch,reg,
294 target_image,dst_x,dst_y)
295Display *disp;
296XImage *reg_image,*target_image ;
297image_region_type *reg;
298int32_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
388static XImage *
389ReadRegionsInList(disp,fakeVis,depth,format,width,height,bbox,regions)
390Display *disp ;
391Visual *fakeVis ;
392int32_t depth , width , height ;
393int32_t format ;
394XRectangle bbox; /* bounding box of grabbed area */
395list_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
476XImage *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 ------------------------------------------------------------------------ **/
670static 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 ------------------------------------------------------------------------ **/
767static 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 ------------------------------------------------------------------------ **/
870void 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 ------------------------------------------------------------------------ **/
880static 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 ------------------------------------------------------------------------ **/
893static 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 ------------------------------------------------------------------------ **/
918static 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 ------------------------------------------------------------------------ **/
940static 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 ------------------------------------------------------------------------ **/
961static 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 ------------------------------------------------------------------------ **/
1000static 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 ------------------------------------------------------------------------ **/
1020static 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
1069static 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
1094int32_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 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; /* Paramters 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
1229void 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() */