Path: blob/master/src/java.desktop/unix/native/libawt_xawt/awt/multiVis.c
41154 views
/*1* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24/** ------------------------------------------------------------------------25This file contains functions to create a list of regions which26tile a specified window. Each region contains all visible27portions of the window which are drawn with the same visual.28If the window consists of subwindows of two different visual types,29there will be two regions in the list. The list can be traversed30to correctly pull an image of the window using XGetImage or the31Image Library.3233This file is available under and governed by the GNU General Public34License version 2 only, as published by the Free Software Foundation.35However, the following notice accompanied the original version of this36file:3738Copyright 1994 Hewlett-Packard Co.39Copyright 1996, 1998 The Open Group4041Permission to use, copy, modify, distribute, and sell this software and its42documentation for any purpose is hereby granted without fee, provided that43the above copyright notice appear in all copies and that both that44copyright notice and this permission notice appear in supporting45documentation.4647The above copyright notice and this permission notice shall be included48in all copies or substantial portions of the Software.4950THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS51OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF52MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.53IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR54OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,55ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR56OTHER DEALINGS IN THE SOFTWARE.5758Except as contained in this notice, the name of The Open Group shall59not be used in advertising or otherwise to promote the sale, use or60other dealings in this Software without prior written authorization61from The Open Group.6263------------------------------------------------------------------------ **/6465#ifdef HEADLESS66#error This file should not be included in headless library67#endif6869#include <stdlib.h>70#include <X11/Xlib.h>71#include <X11/Xutil.h>72#include <X11/X.h>73#include <stdio.h>74#include "list.h"75#include "wsutils.h"76#include "multiVis.h"77/* These structures are copied from X11/region.h. For some reason78* they're invisible from the outside.79*/80typedef struct {81short x1, x2, y1, y2;82} myBox, myBOX, myBoxRec, *myBoxPtr;8384typedef struct my_XRegion {85long size;86long numRects;87myBOX *rects;88myBOX extents;89} myREGION;9091/* Items in long list of windows that have some part in the grabbed area */92typedef struct {93Window win;94Visual *vis;95Colormap cmap;96int x_rootrel, y_rootrel; /* root relative location of window */97int x_vis, y_vis; /* rt rel x,y of vis part, not parent clipped */98int width, height; /* width and height of visible part */99int border_width; /* border width of the window */100Window parent; /* id of parent (for debugging) */101} image_win_type;102103/* Items in short list of regions that tile the grabbed area. May have104multiple windows in the region.105*/106typedef struct {107Window win; /* lowest window of this visual */108Visual *vis;109Colormap cmap;110int x_rootrel, y_rootrel; /* root relative location of bottom window */111int x_vis, y_vis; /* rt rel x,y of vis part, not parent clipped */112int width, height; /* w & h of visible rect of bottom window */113int border; /* border width of the window */114Region visible_region;115} image_region_type;116117/** ------------------------------------------------------------------------118Returns TRUE if the two structs pointed to have the same "vis" &119"cmap" fields and s2 lies completely within s1. s1 and s2 can120point to structs of image_win_type or image_region_type.121------------------------------------------------------------------------ **/122#define SAME_REGIONS( s1, s2) \123((s1)->vis == (s2)->vis && (s1)->cmap == (s2)->cmap && \124(s1)->x_vis <= (s2)->x_vis && \125(s1)->y_vis <= (s2)->y_vis && \126(s1)->x_vis + (s1)->width >= (s2)->x_vis + (s2)->width && \127(s1)->y_vis + (s1)->height >= (s2)->y_vis + (s2)->height)128129#ifndef MIN130#define MIN( a, b) ((a) < (b) ? a : b)131#define MAX( a, b) ((a) > (b) ? a : b)132#endif133134#define RED_SHIFT 16135#define GREEN_SHIFT 8136#define BLUE_SHIFT 0137138/*139extern list_ptr new_list();140extern list_ptr dup_list_head();141extern void * first_in_list();142extern void * next_in_list();143extern int add_to_list();144extern void zero_list();145extern void delete_list();146extern void delete_list_destroying();147extern unsigned int list_length();148*/149150/* Prototype Declarations for Static Functions */151static void QueryColorMap(152Display *, Colormap , Visual *,153XColor **, int *, int *, int *154);155static void TransferImage(156Display *, XImage *,int, int , image_region_type*,157XImage *,int ,int158);159static XImage * ReadRegionsInList(160Display *, Visual *, int, int, unsigned int,161unsigned int, XRectangle, list_ptr162);163164static list_ptr make_region_list(165Display*, Window, XRectangle*,166int*, int, XVisualInfo**, int *167);168169static void destroy_region_list(170list_ptr171) ;172static void subtr_rect_from_image_region(173image_region_type *, int , int , int , int174);175static void add_rect_to_image_region(176image_region_type *,177int , int , int , int178);179static int src_in_region_list(180image_win_type *, list_ptr181);182static void add_window_to_list(183list_ptr, Window, int, int ,184int , int , int , int, int,185Visual*, Colormap, Window186);187static int src_in_image(188image_win_type *, int , XVisualInfo**189);190static int src_in_overlay(191image_region_type *, int, OverlayInfo *, int*, int*192);193static void make_src_list(194Display *, list_ptr, XRectangle *, Window,195int, int, XWindowAttributes *, XRectangle *196);197static void destroy_image_region(198image_region_type *199);200201/* End of Prototype Declarations */202203void initFakeVisual(Visual *Vis)204{205Vis->ext_data=NULL;206Vis->class = DirectColor ;207Vis->red_mask = 0x00FF0000;208Vis->green_mask = 0x0000FF00 ;209Vis->blue_mask = 0x000000FF ;210Vis->map_entries = 256 ;211Vis->bits_per_rgb = 8 ;212}213214static void215QueryColorMap(Display *disp, Colormap src_cmap, Visual *src_vis,216XColor **src_colors, int *rShift, int *gShift, int *bShift)217{218unsigned int ncolors,i ;219unsigned long redMask, greenMask, blueMask;220int redShift, greenShift, blueShift;221XColor *colors ;222223ncolors = (unsigned) src_vis->map_entries ;224/* JDK modification.225* use calloc instead of malloc to initialize allocated memory226* *src_colors = colors = (XColor *)malloc(ncolors * sizeof(XColor) ) ;227*/228*src_colors = colors = (XColor *)calloc(ncolors, sizeof(XColor));229230if(src_vis->class != TrueColor && src_vis->class != DirectColor)231{232for(i=0 ; i < ncolors ; i++)233{234colors[i].pixel = i ;235colors[i].pad = 0;236colors[i].flags = DoRed|DoGreen|DoBlue;237}238}239else /** src is decomposed rgb ***/240{241/* Get the X colormap */242redMask = src_vis->red_mask;243greenMask = src_vis->green_mask;244blueMask = src_vis->blue_mask;245redShift = 0; while (!(redMask&0x1)) {246redShift++;247redMask = redMask>>1;248}249greenShift = 0; while (!(greenMask&0x1)) {250greenShift++;251greenMask = greenMask>>1;252}253blueShift = 0; while (!(blueMask&0x1)) {254blueShift++;255blueMask = blueMask>>1;256}257*rShift = redShift ;258*gShift = greenShift ;259*bShift = blueShift ;260for (i=0; i<ncolors; i++) {261if( i <= redMask)colors[i].pixel = (i<<redShift) ;262if( i <= greenMask)colors[i].pixel |= (i<<greenShift) ;263if( i <= blueMask)colors[i].pixel |= (i<<blueShift) ;264/***** example :for gecko's 3-3-2 map, blue index should be <= 3.265colors[i].pixel = (i<<redShift)|(i<<greenShift)|(i<<blueShift);266*****/267colors[i].pad = 0;268colors[i].flags = DoRed|DoGreen|DoBlue;269}270}271272XQueryColors(disp, src_cmap, colors, (int) ncolors);273}274275int276GetMultiVisualRegions(Display *disp,277/* root win on which grab was done */278Window srcRootWinid,279/* root rel UL corner of bounding box of grab */280int x, int y,281/* size of bounding box of grab */282unsigned int width, unsigned int height,283int *transparentOverlays, int *numVisuals,284XVisualInfo **pVisuals, int *numOverlayVisuals,285OverlayInfo **pOverlayVisuals,286int *numImageVisuals, XVisualInfo ***pImageVisuals,287/* list of regions to read from */288list_ptr *vis_regions,289list_ptr *vis_image_regions, int *allImage)290{291int hasNonDefault;292XRectangle bbox; /* bounding box of grabbed area */293294295bbox.x = x; /* init X rect for bounding box */296bbox.y = y;297bbox.width = width;298bbox.height = height;299300GetXVisualInfo(disp,DefaultScreen(disp),301transparentOverlays,302numVisuals, pVisuals,303numOverlayVisuals, pOverlayVisuals,304numImageVisuals, pImageVisuals);305306*vis_regions = *vis_image_regions = NULL ;307if ((*vis_regions = make_region_list( disp, srcRootWinid, &bbox,308&hasNonDefault, *numImageVisuals,309*pImageVisuals, allImage)) == NULL)310return 0 ;311312if (*transparentOverlays)313{314*allImage = 1; /* until proven otherwise,315this flags that it to be an image only list */316*vis_image_regions =317make_region_list( disp, srcRootWinid, &bbox, &hasNonDefault,318*numImageVisuals, *pImageVisuals, allImage);319}320321/* if there is a second region in any of the two lists return 1 **/322if ( ( *vis_regions && (*vis_regions)->next && (*vis_regions)->next->next ) ||323( *vis_image_regions && (*vis_image_regions)->next &&324(*vis_image_regions)->next->next ) ) return 1 ;325else return 0 ;326327}328329static void TransferImage(Display *disp, XImage *reg_image,330int srcw, int srch,331image_region_type *reg, XImage *target_image,332int dst_x, int dst_y)333{334int i,j,old_pixel,new_pixel,red_ind,green_ind,blue_ind ;335XColor *colors;336int rShift = 0, gShift = 0, bShift = 0;337338QueryColorMap(disp,reg->cmap,reg->vis,&colors,339&rShift,&gShift,&bShift) ;340341switch (reg->vis->class) {342case TrueColor :343for(i=0 ; i < srch ; i++)344{345for(j=0 ; j < srcw ; j++)346{347old_pixel = XGetPixel(reg_image,j,i) ;348349/*350* JDK modification.351* commented out since not using server RGB masks in all true color modes352* causes the R and B values to be swapped around on some X servers353* - robi.khan@eng 9/7/1999354* if( reg->vis->map_entries == 16) {355*/356red_ind = (old_pixel & reg->vis->red_mask) >> rShift ;357green_ind = (old_pixel & reg->vis->green_mask) >> gShift ;358blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ;359360new_pixel = (361((colors[red_ind].red >> 8) << RED_SHIFT)362|((colors[green_ind].green >> 8) << GREEN_SHIFT)363|((colors[blue_ind].blue >> 8) << BLUE_SHIFT)364);365/* JDK modification.366* else part of above modification367*368* }369* else370* new_pixel = old_pixel;371*/372373XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);374375}376}377break;378case DirectColor :379for(i=0 ; i < srch ; i++)380{381382for(j=0 ; j < srcw ; j++)383{384old_pixel = XGetPixel(reg_image,j,i) ;385red_ind = (old_pixel & reg->vis->red_mask) >> rShift ;386green_ind = (old_pixel & reg->vis->green_mask) >> gShift ;387blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ;388389new_pixel = (390((colors[red_ind].red >> 8) << RED_SHIFT)391|((colors[green_ind].green >> 8) << GREEN_SHIFT)392|((colors[blue_ind].blue >> 8) << BLUE_SHIFT)393);394XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);395396}397}398break;399default :400for(i=0 ; i < srch ; i++)401{402for(j=0 ; j < srcw ; j++)403{404old_pixel = XGetPixel(reg_image,j,i) ;405406new_pixel = (407((colors[old_pixel].red >> 8) << RED_SHIFT)408|((colors[old_pixel].green >> 8) << GREEN_SHIFT)409|((colors[old_pixel].blue >> 8) << BLUE_SHIFT)410);411XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);412413}414}415break;416}417/* JDK modification418* Fix memory leak by freeing colors419* - robi.khan@eng 9/22/1999420*/421free(colors);422}423424static XImage *425ReadRegionsInList(Display *disp, Visual *fakeVis, int depth, int format,426unsigned int width, unsigned int height,427XRectangle bbox, /* bounding box of grabbed area */428list_ptr regions) /* list of regions to read from */429{430image_region_type *reg;431int dst_x, dst_y; /* where in pixmap to write (UL) */432int diff;433434XImage *reg_image,*ximage ;435int srcRect_x,srcRect_y,srcRect_width,srcRect_height ;436int bytes_per_line;437438ximage = XCreateImage(disp,fakeVis,depth,format,0,NULL,width,height,4398,0) ;440bytes_per_line = ximage->bytes_per_line;441442if (format == ZPixmap)443ximage->data = malloc((size_t) height * bytes_per_line);444else445ximage->data = malloc((size_t) height * bytes_per_line * depth);446447ximage->bits_per_pixel = depth; /** Valid only if format is ZPixmap ***/448449for (reg = (image_region_type *) first_in_list( regions); reg;450reg = (image_region_type *) next_in_list( regions))451{452int rect;453struct my_XRegion *vis_reg;454vis_reg = (struct my_XRegion *)(reg->visible_region);455for (rect = 0;456rect < vis_reg->numRects;457rect++)458{459/** ------------------------------------------------------------------------460Intersect bbox with visible part of region giving src rect & output461location. Width is the min right side minus the max left side.462Similar for height. Offset src rect so x,y are relative to463origin of win, not the root-relative visible rect of win.464------------------------------------------------------------------------ **/465srcRect_width = MIN( vis_reg->rects[rect].x2, bbox.width + bbox.x) -466MAX( vis_reg->rects[rect].x1, bbox.x);467srcRect_height = MIN( vis_reg->rects[rect].y2, bbox.height + bbox.y) -468MAX( vis_reg->rects[rect].y1, bbox.y);469diff = bbox.x - vis_reg->rects[rect].x1;470srcRect_x = MAX( 0, diff) + (vis_reg->rects[rect].x1 - reg->x_rootrel - reg->border);471dst_x = MAX( 0, -diff) ;472diff = bbox.y - vis_reg->rects[rect].y1;473srcRect_y = MAX( 0, diff) + (vis_reg->rects[rect].y1 - reg->y_rootrel - reg->border);474dst_y = MAX( 0, -diff) ;475reg_image = XGetImage(disp,reg->win,srcRect_x,srcRect_y,476srcRect_width,srcRect_height,AllPlanes,format) ;477478/* JDK Modification479* Enclose in if test and also call XDestroyImage480*/481if (reg_image) {482TransferImage(disp,reg_image,srcRect_width,483srcRect_height,reg,ximage,dst_x,dst_y) ;484XDestroyImage(reg_image);485}486}487}488return ximage ;489}490491492/** ------------------------------------------------------------------------493------------------------------------------------------------------------ **/494495XImage *ReadAreaToImage(Display *disp,496/* root win on which grab was done */497Window srcRootWinid,498/* root rel UL corner of bounding box of grab */499int x, int y,500/* size of bounding box of grab */501unsigned int width, unsigned int height,502int numVisuals, XVisualInfo *pVisuals,503int numOverlayVisuals, OverlayInfo *pOverlayVisuals,504int numImageVisuals, XVisualInfo **pImageVisuals,505/* list of regions to read from */506list_ptr vis_regions,507/* list of regions to read from */508list_ptr vis_image_regions,509int format, int allImage)510{511image_region_type *reg;512XRectangle bbox; /* bounding box of grabbed area */513int depth ;514XImage *ximage, *ximage_ipm = NULL;515Visual fakeVis ;516int x1, y1;517XImage *image;518#if 0519unsigned char *pmData , *ipmData ;520#endif521int transparentColor, transparentType;522int srcRect_x,srcRect_y,srcRect_width,srcRect_height ;523int diff ;524int dst_x, dst_y; /* where in pixmap to write (UL) */525int pixel;526527bbox.x = x; /* init X rect for bounding box */528bbox.y = y;529bbox.width = width;530bbox.height = height;531532533initFakeVisual(&fakeVis) ;534535depth = 24 ;536ximage = ReadRegionsInList(disp,&fakeVis,depth,format,width,height,537bbox,vis_regions) ;538#if 0539pmData = (unsigned char *)ximage -> data ;540#endif541542/* if transparency possible do it again, but this time for image planes only */543if (vis_image_regions && (vis_image_regions->next) && !allImage)544{545ximage_ipm = ReadRegionsInList(disp,&fakeVis,depth,format,width,height,546bbox,vis_image_regions) ;547#if 0548ipmData = (unsigned char *)ximage_ipm -> data ;549#endif550}551/* Now tranverse the overlay visual windows and test for transparency index. */552/* If you find one, subsitute the value from the matching image plane pixmap. */553554for (reg = (image_region_type *) first_in_list( vis_regions); reg;555reg = (image_region_type *) next_in_list( vis_regions))556{557558if (src_in_overlay( reg, numOverlayVisuals, pOverlayVisuals,559&transparentColor, &transparentType))560{561int test = 0 ;562srcRect_width = MIN( reg->width + reg->x_vis, bbox.width + bbox.x)563- MAX( reg->x_vis, bbox.x);564srcRect_height = MIN( reg->height + reg->y_vis, bbox.height565+ bbox.y) - MAX( reg->y_vis, bbox.y);566diff = bbox.x - reg->x_vis;567srcRect_x = MAX( 0, diff) + (reg->x_vis - reg->x_rootrel - reg->border);568dst_x = MAX( 0, -diff) ;569diff = bbox.y - reg->y_vis;570srcRect_y = MAX( 0, diff) + (reg->y_vis - reg->y_rootrel - reg->border);571dst_y = MAX( 0, -diff) ;572/* let's test some pixels for transparency */573image = XGetImage(disp, reg->win, srcRect_x, srcRect_y,574srcRect_width, srcRect_height, 0xffffffff, ZPixmap);575576/* let's assume byte per pixel for overlay image for now */577if ((image->depth == 8) && (transparentType == TransparentPixel))578{579unsigned char *pixel_ptr;580unsigned char *start_of_line = (unsigned char *) image->data;581582for (y1 = 0; y1 < srcRect_height; y1++) {583pixel_ptr = start_of_line;584for (x1 = 0; x1 < srcRect_width; x1++)585{586if (*pixel_ptr++ == transparentColor)587{588#if 0589*pmData++ = *ipmData++;590*pmData++ = *ipmData++;591*pmData++ = *ipmData++;592#endif593pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;594XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);595596if(!test){597test = 1 ;598}599}600#if 0601else {602pmData +=3;603ipmData +=3;604}605#endif606}607start_of_line += image->bytes_per_line;608}609} else {610if (transparentType == TransparentPixel) {611for (y1 = 0; y1 < srcRect_height; y1++) {612for (x1 = 0; x1 < srcRect_width; x1++)613{614int pixel_value = XGetPixel(image, x1, y1);615if (pixel_value == transparentColor)616{617#if 0618*pmData++ = *ipmData++;619*pmData++ = *ipmData++;620*pmData++ = *ipmData++;621#endif622pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;623XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);624if(!test){625test = 1 ;626}627}628#if 0629else {630pmData +=3;631ipmData +=3;632}633#endif634}635}636} else {637for (y1 = 0; y1 < srcRect_height; y1++) {638for (x1 = 0; x1 < srcRect_width; x1++)639{640int pixel_value = XGetPixel(image, x1, y1);641if (pixel_value & transparentColor)642{643#if 0644*pmData++ = *ipmData++;645*pmData++ = *ipmData++;646*pmData++ = *ipmData++;647#endif648pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;649XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);650if(!test){651test = 1 ;652}653}654#if 0655else {656pmData +=3;657ipmData +=3;658}659#endif660}661}662}663}664XDestroyImage (image);665} /* end of src_in_overlay */666} /** end transparency **/667/* JDK modification - call XDestroyImage if non-null */668if (ximage_ipm != NULL) {669XDestroyImage(ximage_ipm);670}671destroy_region_list( vis_regions);672if (vis_image_regions) destroy_region_list( vis_image_regions );673FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals);674XSync(disp, 0);675676return ximage;677}678679/** ------------------------------------------------------------------------680Creates a list of the subwindows of a given window which have a681different visual than their parents. The function is recursive.682This list is used in make_region_list(), which coalesces the683windows with the same visual into a region.684image_wins must point to an existing list struct that's already685been zeroed (zero_list()).686------------------------------------------------------------------------ **/687static void make_src_list(Display *disp, list_ptr image_wins,688/* bnding box of area we want */689XRectangle *bbox,690Window curr,691/* pos of curr WRT root */692int x_rootrel, int y_rootrel,693XWindowAttributes *curr_attrs,694/* visible part of curr, not obscurred by ancestors */695XRectangle *pclip)696{697XWindowAttributes child_attrs;698Window root, parent, *child; /* variables for XQueryTree() */699Window *save_child_list; /* variables for XQueryTree() */700unsigned int nchild; /* variables for XQueryTree() */701XRectangle child_clip; /* vis part of child */702int curr_clipX, curr_clipY, curr_clipRt, curr_clipBt;703704/* check that win is mapped & not outside bounding box */705if (curr_attrs->map_state == IsViewable &&706curr_attrs->class == InputOutput &&707!( pclip->x >= (int) (bbox->x + bbox->width) ||708pclip->y >= (int) (bbox->y + bbox->height) ||709(int) (pclip->x + pclip->width) <= bbox->x ||710(int) (pclip->y + pclip->height) <= bbox->y)) {711712XQueryTree( disp, curr, &root, &parent, &child, &nchild );713save_child_list = child; /* so we can free list when we're done */714add_window_to_list( image_wins, curr, x_rootrel, y_rootrel,715pclip->x, pclip->y,716pclip->width, pclip->height,717curr_attrs->border_width,curr_attrs->visual,718curr_attrs->colormap, parent);719720721/** ------------------------------------------------------------------------722set RR coords of right (Rt), left (X), bottom (Bt) and top (Y)723of rect we clip all children by. This is our own clip rect (pclip)724inflicted on us by our parent plus our own borders. Within the725child loop, we figure the clip rect for each child by adding in726it's rectangle (not taking into account the child's borders).727------------------------------------------------------------------------ **/728curr_clipX = MAX( pclip->x, x_rootrel + (int) curr_attrs->border_width);729curr_clipY = MAX( pclip->y, y_rootrel + (int) curr_attrs->border_width);730curr_clipRt = MIN( pclip->x + (int) pclip->width,731x_rootrel + (int) curr_attrs->width +7322 * (int) curr_attrs->border_width);733curr_clipBt = MIN( pclip->y + (int) pclip->height,734y_rootrel + (int) curr_attrs->height +7352 * (int) curr_attrs->border_width);736737while (nchild--) {738int new_width, new_height;739int child_xrr, child_yrr; /* root relative x & y of child */740741XGetWindowAttributes( disp, *child, &child_attrs);742743/* intersect parent & child clip rects */744child_xrr = x_rootrel + child_attrs.x + curr_attrs->border_width;745child_clip.x = MAX( curr_clipX, child_xrr);746new_width = MIN( curr_clipRt, child_xrr + (int) child_attrs.width747+ 2 * child_attrs.border_width)748- child_clip.x;749if (new_width >= 0) {750child_clip.width = new_width;751752child_yrr = y_rootrel + child_attrs.y +753curr_attrs->border_width;754child_clip.y = MAX( curr_clipY, child_yrr);755new_height = MIN( curr_clipBt,756child_yrr + (int) child_attrs.height +7572 * child_attrs.border_width)758- child_clip.y;759if (new_height >= 0) {760child_clip.height = new_height;761make_src_list( disp, image_wins, bbox, *child,762child_xrr, child_yrr,763&child_attrs, &child_clip);764}765}766child++;767}768XFree( save_child_list);769}770}771772773/** ------------------------------------------------------------------------774This function creates a list of regions which tile a specified775window. Each region contains all visible portions of the window776which are drawn with the same visual. For example, if the777window consists of subwindows of two different visual types,778there will be two regions in the list.779Returns a pointer to the list.780------------------------------------------------------------------------ **/781static list_ptr make_region_list(Display *disp, Window win, XRectangle *bbox,782int *hasNonDefault, int numImageVisuals,783XVisualInfo **pImageVisuals, int *allImage)784{785XWindowAttributes win_attrs;786list image_wins;787list_ptr image_regions;788list_ptr srcs_left;789image_region_type *new_reg;790image_win_type *base_src, *src;791Region bbox_region = XCreateRegion();792XRectangle clip;793int image_only;794795int count=0 ;796797*hasNonDefault = False;798XUnionRectWithRegion( bbox, bbox_region, bbox_region);799XGetWindowAttributes( disp, win, &win_attrs);800801zero_list( &image_wins);802clip.x = 0;803clip.y = 0;804clip.width = win_attrs.width;805clip.height = win_attrs.height;806make_src_list( disp, &image_wins, bbox, win,8070 /* x_rootrel */, 0 /* y_rootrel */, &win_attrs, &clip);808809image_regions = new_list();810image_only = (*allImage) ? True:False;811812for (base_src = (image_win_type *) first_in_list( &image_wins); base_src;813base_src = (image_win_type *) next_in_list( &image_wins))814{815/* test for image visual */816if (!image_only || src_in_image(base_src, numImageVisuals, pImageVisuals))817{818/* find a window whose visual hasn't been put in list yet */819if (!src_in_region_list( base_src, image_regions))820{821if (! (new_reg = (image_region_type *)822malloc( sizeof( image_region_type)))) {823return (list_ptr) NULL;824}825count++;826827new_reg->visible_region = XCreateRegion();828new_reg->win = base_src->win;829new_reg->vis = base_src->vis;830new_reg->cmap = base_src->cmap;831new_reg->x_rootrel = base_src->x_rootrel;832new_reg->y_rootrel = base_src->y_rootrel;833new_reg->x_vis = base_src->x_vis;834new_reg->y_vis = base_src->y_vis;835new_reg->width = base_src->width;836new_reg->height = base_src->height;837new_reg->border = base_src->border_width;838839srcs_left = (list_ptr) dup_list_head( &image_wins, START_AT_CURR);840for (src = (image_win_type *) first_in_list( srcs_left); src;841src = (image_win_type *) next_in_list( srcs_left)) {842if (SAME_REGIONS( base_src, src)) {843add_rect_to_image_region( new_reg, src->x_vis, src->y_vis,844src->width, src->height);845}846else {847if (!image_only || src_in_image(src, numImageVisuals, pImageVisuals))848{849subtr_rect_from_image_region( new_reg, src->x_vis,850src->y_vis, src->width, src->height);851}852}853}854XIntersectRegion( bbox_region, new_reg->visible_region,855new_reg->visible_region);856if (! XEmptyRegion( new_reg->visible_region)) {857add_to_list( image_regions, new_reg);858if (new_reg->vis != DefaultVisualOfScreen( win_attrs.screen) ||859new_reg->cmap != DefaultColormapOfScreen(860win_attrs.screen)) {861*hasNonDefault = True;862}863}864else {865XDestroyRegion( new_reg->visible_region);866free( (void *) new_reg);867}868}869} else *allImage = 0;870}871delete_list( &image_wins, True);872XDestroyRegion( bbox_region);873return image_regions;874}875/** ------------------------------------------------------------------------876Destructor called from destroy_region_list().877------------------------------------------------------------------------ **/878static void destroy_image_region(image_region_type *image_region)879{880XDestroyRegion( image_region->visible_region);881free( (void *) image_region);882}883884/** ------------------------------------------------------------------------885Destroys the region list, destroying all the regions contained in it.886------------------------------------------------------------------------ **/887static void destroy_region_list(list_ptr rlist)888{889delete_list_destroying( rlist, (DESTRUCT_FUNC_PTR)destroy_image_region);890}891892893/** ------------------------------------------------------------------------894Subtracts the specified rectangle from the region in image_region.895First converts the rectangle to a region of its own, since X896only provides a way to subtract one region from another, not a897rectangle from a region.898------------------------------------------------------------------------ **/899static void subtr_rect_from_image_region(image_region_type *image_region,900int x, int y, int width, int height)901{902XRectangle rect;903Region rect_region;904905rect_region = XCreateRegion();906rect.x = x;907rect.y = y;908rect.width = width;909rect.height = height;910XUnionRectWithRegion( &rect, rect_region, rect_region);911XSubtractRegion( image_region->visible_region, rect_region,912image_region->visible_region);913XDestroyRegion( rect_region);914}915916917/** ------------------------------------------------------------------------918Adds the specified rectangle to the region in image_region.919------------------------------------------------------------------------ **/920static void add_rect_to_image_region(image_region_type *image_region,921int x, int y, int width, int height)922{923XRectangle rect;924925rect.x = x;926rect.y = y;927rect.width = width;928rect.height = height;929XUnionRectWithRegion( &rect, image_region->visible_region,930image_region->visible_region);931}932933934/** ------------------------------------------------------------------------935Returns TRUE if the given src's visual is already represented in936the image_regions list, FALSE otherwise.937------------------------------------------------------------------------ **/938static int src_in_region_list(image_win_type *src, list_ptr image_regions)939{940image_region_type *ir;941942for (ir = (image_region_type *) first_in_list( image_regions); ir;943ir = (image_region_type *) next_in_list( image_regions)) {944if (SAME_REGIONS( ir, src)) {945946return 1;947}948}949950return 0;951}952953954/** ------------------------------------------------------------------------955Makes a new entry in image_wins with the given fields filled in.956------------------------------------------------------------------------ **/957static void add_window_to_list(list_ptr image_wins, Window w,958int xrr, int yrr, int x_vis, int y_vis,959int width, int height, int border_width,960Visual *vis, Colormap cmap, Window parent)961{962image_win_type *new_src;963964if ((new_src = (image_win_type *) malloc( sizeof( image_win_type))) == NULL)965966return;967968new_src->win = w;969new_src->x_rootrel = xrr;970new_src->y_rootrel = yrr;971new_src->x_vis = x_vis;972new_src->y_vis = y_vis;973new_src->width = width;974new_src->height = height;975new_src->border_width = border_width;976new_src->vis = vis;977new_src->cmap = cmap;978new_src->parent = parent;979add_to_list( image_wins, new_src);980}981982/** ------------------------------------------------------------------------983Returns TRUE if the given src's visual is in the image planes,984FALSE otherwise.985------------------------------------------------------------------------ **/986static int src_in_image(image_win_type *src, int numImageVisuals,987XVisualInfo **pImageVisuals)988{989int i;990991for (i = 0 ; i < numImageVisuals ; i++)992{993if (pImageVisuals[i]->visual == src->vis)994return 1;995}996return 0;997}9989991000/** ------------------------------------------------------------------------1001Returns TRUE if the given src's visual is in the overlay planes1002and transparency is possible, FALSE otherwise.1003------------------------------------------------------------------------ **/1004static int src_in_overlay(image_region_type *src, int numOverlayVisuals,1005OverlayInfo *pOverlayVisuals,1006int *transparentColor, int *transparentType)1007{1008int i;10091010for (i = 0 ; i < numOverlayVisuals ; i++)1011{1012if (((pOverlayVisuals[i].pOverlayVisualInfo)->visual == src->vis)1013&& (pOverlayVisuals[i].transparentType != None))1014{1015*transparentColor = pOverlayVisuals[i].value;1016*transparentType = pOverlayVisuals[i].transparentType;1017return 1;1018}10191020else {1021}10221023}1024return 0;1025}102610271028/********************** from wsutils.c ******************************/10291030/******************************************************************************1031*1032* This file contains a set of example utility procedures; procedures that can1033* help a "window-smart" Starbase or PHIGS program determine information about1034* a device, and create image and overlay plane windows. To use these1035* utilities, #include "wsutils.h" and compile this file and link the results1036* with your program.1037*1038******************************************************************************/1039104010411042#define STATIC_GRAY 0x011043#define GRAY_SCALE 0x021044#define PSEUDO_COLOR 0x041045#define TRUE_COLOR 0x101046#define DIRECT_COLOR 0x11104710481049static int weCreateServerOverlayVisualsProperty = False;105010511052/******************************************************************************1053*1054* GetXVisualInfo()1055*1056* This routine takes an X11 Display, screen number, and returns whether the1057* screen supports transparent overlays and three arrays:1058*1059* 1) All of the XVisualInfo struct's for the screen.1060* 2) All of the OverlayInfo struct's for the screen.1061* 3) An array of pointers to the screen's image plane XVisualInfo1062* structs.1063*1064* The code below obtains the array of all the screen's visuals, and obtains1065* the array of all the screen's overlay visual information. It then processes1066* the array of the screen's visuals, determining whether the visual is an1067* overlay or image visual.1068*1069* If the routine sucessfully obtained the visual information, it returns zero.1070* If the routine didn't obtain the visual information, it returns non-zero.1071*1072******************************************************************************/10731074int GetXVisualInfo(/* Which X server (aka "display"). */1075Display *display,1076/* Which screen of the "display". */1077int screen,1078/* Non-zero if there's at least one overlay visual and1079* if at least one of those supports a transparent pixel. */1080int *transparentOverlays,1081/* Number of XVisualInfo struct's pointed to by pVisuals. */1082int *numVisuals,1083/* All of the device's visuals. */1084XVisualInfo **pVisuals,1085/* Number of OverlayInfo's pointed to by pOverlayVisuals.1086* If this number is zero, the device does not have1087* overlay planes. */1088int *numOverlayVisuals,1089/* The device's overlay plane visual information. */1090OverlayInfo **pOverlayVisuals,1091/* Number of XVisualInfo's pointed to by pImageVisuals. */1092int *numImageVisuals,1093/* The device's image visuals. */1094XVisualInfo ***pImageVisuals)1095{1096XVisualInfo getVisInfo; /* Paramters of XGetVisualInfo */1097int mask;1098XVisualInfo *pVis, **pIVis; /* Faster, local copies */1099OverlayInfo *pOVis;1100OverlayVisualPropertyRec *pOOldVis;1101int nVisuals, nOVisuals;1102Atom overlayVisualsAtom; /* Parameters for XGetWindowProperty */1103Atom actualType;1104unsigned long numLongs, bytesAfter;1105int actualFormat;1106int nImageVisualsAlloced; /* Values to process the XVisualInfo */1107int imageVisual; /* array */110811091110/* First, get the list of visuals for this screen. */1111getVisInfo.screen = screen;1112mask = VisualScreenMask;11131114*pVisuals = XGetVisualInfo(display, mask, &getVisInfo, numVisuals);1115if ((nVisuals = *numVisuals) <= 0)1116{1117/* Return that the information wasn't sucessfully obtained: */1118return(1);1119}1120pVis = *pVisuals;112111221123/* Now, get the overlay visual information for this screen. To obtain1124* this information, get the SERVER_OVERLAY_VISUALS property.1125*/1126overlayVisualsAtom = XInternAtom(display, "SERVER_OVERLAY_VISUALS", True);1127if (overlayVisualsAtom != None)1128{1129/* Since the Atom exists, we can request the property's contents. The1130* do-while loop makes sure we get the entire list from the X server.1131*/1132bytesAfter = 0;1133numLongs = sizeof(OverlayVisualPropertyRec) / sizeof(long);1134do1135{1136numLongs += bytesAfter * sizeof(long);1137XGetWindowProperty(display, RootWindow(display, screen),1138overlayVisualsAtom, 0, numLongs, False,1139overlayVisualsAtom, &actualType, &actualFormat,1140&numLongs, &bytesAfter, (unsigned char**) pOverlayVisuals);1141} while (bytesAfter > 0);114211431144/* Calculate the number of overlay visuals in the list. */1145*numOverlayVisuals = numLongs / (sizeof(OverlayVisualPropertyRec) / sizeof(long));1146}1147else1148{1149/* This screen doesn't have overlay planes. */1150*numOverlayVisuals = 0;1151*pOverlayVisuals = NULL;1152*transparentOverlays = 0;1153}115411551156/* Process the pVisuals array. */1157*numImageVisuals = 0;1158nImageVisualsAlloced = 1;1159pIVis = *pImageVisuals = (XVisualInfo **) malloc(sizeof(XVisualInfo *));1160while (--nVisuals >= 0)1161{1162nOVisuals = *numOverlayVisuals;1163pOVis = *pOverlayVisuals;1164imageVisual = True;1165while (--nOVisuals >= 0)1166{1167pOOldVis = (OverlayVisualPropertyRec *) pOVis;1168if (pVis->visualid == pOOldVis->visualID)1169{1170imageVisual = False;1171pOVis->pOverlayVisualInfo = pVis;1172if (pOVis->transparentType == TransparentPixel)1173*transparentOverlays = 1;1174}1175pOVis++;1176}1177if (imageVisual)1178{1179if ((*numImageVisuals += 1) > nImageVisualsAlloced)1180{1181nImageVisualsAlloced++;1182*pImageVisuals = (XVisualInfo **)1183realloc(*pImageVisuals, (nImageVisualsAlloced * sizeof(XVisualInfo *)));1184pIVis = *pImageVisuals + (*numImageVisuals - 1);1185}1186*pIVis++ = pVis;1187}1188pVis++;1189}119011911192/* Return that the information was sucessfully obtained: */1193return(0);11941195} /* GetXVisualInfo() */119611971198/******************************************************************************1199*1200* FreeXVisualInfo()1201*1202* This routine frees the data that was allocated by GetXVisualInfo().1203*1204******************************************************************************/12051206void FreeXVisualInfo(XVisualInfo *pVisuals, OverlayInfo *pOverlayVisuals,1207XVisualInfo **pImageVisuals)1208{1209XFree(pVisuals);1210if (weCreateServerOverlayVisualsProperty)1211free(pOverlayVisuals);1212else1213XFree(pOverlayVisuals);1214free(pImageVisuals);12151216} /* FreeXVisualInfo() */121712181219