multivis.c revision 1233
469N/A/*-
469N/A * multivis.c - Mechanism for GetImage across Multiple Visuals
469N/A *
1068N/A * Original author:
1068N/A * Milind M. Pansare
1068N/A * Window Systems Group
1068N/A * Sun Microsystems, Inc.
1068N/A *
1068N/A * Revision History:
1068N/A * 11-15-90 Written
1068N/A */
1068N/A
1068N/A/* Copyright (c) 1990, 2011, Oracle and/or its affiliates. All rights reserved.
469N/A *
919N/A * Permission is hereby granted, free of charge, to any person obtaining a
919N/A * copy of this software and associated documentation files (the "Software"),
919N/A * to deal in the Software without restriction, including without limitation
919N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense,
919N/A * and/or sell copies of the Software, and to permit persons to whom the
919N/A * Software is furnished to do so, subject to the following conditions:
919N/A *
919N/A * The above copyright notice and this permission notice (including the next
919N/A * paragraph) shall be included in all copies or substantial portions of the
919N/A * Software.
469N/A *
919N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
919N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
919N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
919N/A * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
919N/A * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
919N/A * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
919N/A * DEALINGS IN THE SOFTWARE.
469N/A */
469N/A
1068N/A#include <stdlib.h>
469N/A#include <X11/Xlib.h>
469N/A#include <X11/Xutil.h>
469N/A#ifdef SHAPE
469N/A#include <X11/extensions/shape.h>
469N/A#endif /* SHAPE */
469N/A#include "multivis.h"
469N/A
1233N/Astatic MVColmap *mvFindColormap(Colormap cmap);
1233N/Astatic XVisualInfo *mvMatchVisual(VisualID vid);
1233N/Astatic void mvGetColormap(MVWinVisInfo *pWI);
1233N/Astatic void mvCalculateComposite(MVWinVisInfo *pWI);
1233N/Astatic unsigned long mvCompositePixel(unsigned long i, MVColmap *pCmp);
469N/A
469N/Astatic Display *mvDpy; /* Display */
469N/Astatic int mvScreen; /* Screen */
469N/Astatic XVisualInfo *mvVlist; /* List of Visuals */
469N/Astatic int mvNumVis; /* Number of visuals in list */
469N/A#ifdef SHAPE
469N/Astatic Bool mvShape; /* Shape extension ? */
469N/A#endif /* SHAPE */
469N/A
469N/Astatic MVWinVisInfoList winList; /* Here we'll grow a list of windows
469N/A Sorted back to front */
469N/A
469N/Astatic MVColmap *colMaps; /* list of colormaps we encounter */
469N/Astatic MVPel *mvImg; /* mvImg is what we compose the image
469N/A into */
469N/A
469N/Astatic int request_width,
469N/A request_height; /* size of requested rectangle */
469N/Astatic int request_x, request_y; /* The top left of requested
469N/A rectangle in Root Space */
469N/A
469N/A#ifdef UPDATE_HACK
469N/Astatic void *mvCallbackData;
469N/Astatic mvCallbackFunc mvCallbackFunction;
469N/A#endif /* UPDATE_HACK */
469N/A
469N/A
469N/A/*
469N/A * Initialise the mvLib routines ...
469N/A*/
469N/A
469N/Avoid
469N/A#ifdef UPDATE_HACK
1233N/AmvInit(
1233N/A Display *dpy,
1233N/A int screen,
1233N/A XVisualInfo *vlist,
1233N/A int num_vis,
1233N/A void *callbackData,
1233N/A mvCallbackFunc callbackFunction)
469N/A#else
1233N/AmvInit(
1233N/A Display *dpy,
1233N/A int screen,
1233N/A XVisualInfo *vlist,
1233N/A int num_vis)
469N/A#endif /* UPDATE_HACK */
469N/A{
469N/A#ifdef SHAPE
469N/A int tmp;
469N/A#endif /* SHAPE */
469N/A /* Initialise screen info */
469N/A mvDpy = dpy;
469N/A mvScreen = screen;
469N/A mvVlist = vlist;
469N/A mvNumVis = num_vis;
469N/A#ifdef SHAPE
469N/A mvShape = XShapeQueryExtension(dpy, &tmp, &tmp);
469N/A#endif /* SHAPE */
469N/A
469N/A#ifdef UPDATE_HACK
469N/A mvCallbackData = callbackData;
469N/A mvCallbackFunction = callbackFunction;
469N/A#endif /* UPDATE_HACK */
469N/A}
469N/A
469N/A/*
469N/A * Create an Img.. Cleared to zeros.
469N/A * returns 0 if failure, non-zero for success.
469N/A * Note that it is the reponsibility of the caller
469N/A * to verify that any resulting XGetImage will
469N/A * be within the bounds of the screen.
469N/A * i.e, x, y, wd, ht must be such that the rectangle
469N/A * is fully within the bounds of the screen.
469N/A*/
469N/Aint
1233N/AmvCreatImg(int wd, int ht, int x, int y)
469N/A{
469N/A /* Create mvImg */
469N/A request_width = wd;
469N/A request_height = ht;
469N/A request_x = x;
469N/A request_y = y;
469N/A if ((mvImg = (MVPel *) calloc(sizeof(MVPel), request_width * request_height))
469N/A != NULL) {
469N/A return 1;
469N/A }
469N/A return 0;
469N/A}
469N/A
469N/A/*
469N/A * Reset the mvLib routines
469N/A*/
469N/Avoid
1233N/AmvReset(void)
469N/A{
469N/A#ifdef SHAPE
469N/A int i;
469N/A#endif /* SHAPE */
469N/A /* Free mvImg */
469N/A if (mvImg)
469N/A free(mvImg);
469N/A /* Clean winList */
469N/A if (winList.wins) {
469N/A#ifdef SHAPE
469N/A i = winList.used;
469N/A while (i--) {
469N/A if (winList.wins[i].region)
469N/A XDestroyRegion(winList.wins[i].region);
469N/A }
469N/A#endif /* SHAPE */
469N/A free(winList.wins);
469N/A winList.wins = NULL;
469N/A winList.used = winList.allocated = 0;
469N/A }
469N/A /* Clean colmap list */
469N/A while (colMaps) {
469N/A MVColmap *pCmap;
469N/A pCmap = colMaps;
469N/A colMaps = pCmap->next;
469N/A if (pCmap->Colors)
469N/A free(pCmap->Colors);
469N/A free(pCmap);
469N/A }
469N/A}
469N/A
469N/A/*
469N/A * Recursively walk the window tree.
469N/A * Find windows that intersect the requested region.
469N/A * Create a list of such windows in global winList.
469N/A * Assumes winList was cleared beforehand.
469N/A*/
469N/Avoid
1233N/AmvWalkTree(
1233N/A Window win, /* This window */
1233N/A int px, int py, /* parent's origin in root space */
1233N/A int x, int y, /* Top left of requested rectangle in root space */
1233N/A int wi, int hi, /* size of requested rectangle */
469N/A#ifdef SHAPE
1233N/A Bool ancestorShaped, /* ancestor was a Shaped window */
1233N/A Region ancestorRegion /* parent rel. effective Bounding region of ancestors */
469N/A#endif /* SHAPE */
1233N/A )
469N/A{
469N/A XWindowAttributes xwa;
469N/A int width, height, x1, y1;
469N/A Window root, parent, *children;
469N/A int n;
469N/A unsigned int nchild;
469N/A MVWinVisInfo *pWinInfo;
469N/A#ifdef SHAPE
469N/A Bool isShaped = False;
469N/A Bool bdg, clp;
469N/A int xb, yb, xc, yc;
469N/A unsigned int wb, hb, wc, hc;
469N/A int count, ordering;
469N/A Region tmpancestorRegion, tmpreg;
469N/A XRectangle *rects, *rect, tmprct;
469N/A#endif /* SHAPE */
469N/A
469N/A if (!XGetWindowAttributes(mvDpy, win, &xwa)
469N/A || xwa.map_state != IsViewable
469N/A || xwa.class == InputOnly) {
469N/A return;
469N/A }
469N/A
469N/A /* compute top-left of image in root space */
469N/A x1 = max(x, xwa.x+px);
469N/A y1 = max(y, xwa.y+py);
469N/A width = min(x+wi, xwa.x+xwa.width+2*xwa.border_width+px)-x1;
469N/A height=min(y+hi, xwa.y+xwa.height+2*xwa.border_width+py)-y1;
469N/A
469N/A if (width <=0 || height <= 0) {
469N/A return;
469N/A }
469N/A
469N/A /* We're interested ... */
469N/A
469N/A if (winList.used >= winList.allocated) { /* expand or create the array */
469N/A winList.allocated = (winList.allocated?winList.allocated*MV_WIN_TUNE2:
469N/A MV_WIN_TUNE1);
469N/A winList.wins = (MVWinVisInfo *)(winList.wins ?
469N/A realloc(winList.wins,winList.allocated*sizeof(MVWinVisInfo)):
469N/A malloc(winList.allocated*sizeof(MVWinVisInfo)));
469N/A }
469N/A
469N/A pWinInfo = &(winList.wins[winList.used++]);
469N/A pWinInfo->window = win;
469N/A pWinInfo->depth = xwa.depth;
469N/A pWinInfo->visinfo = mvMatchVisual(XVisualIDFromVisual(xwa.visual));
469N/A pWinInfo->colmap = mvFindColormap(xwa.colormap);
469N/A pWinInfo->x = x1-xwa.border_width-xwa.x-px;
469N/A pWinInfo->y = y1-xwa.border_width-xwa.y-py;
469N/A pWinInfo->width = width;
469N/A pWinInfo->height = height;
469N/A pWinInfo->x1 = x1;
469N/A pWinInfo->y1 = y1;
469N/A#ifdef SHAPE
469N/A pWinInfo->region = NULL;
469N/A /* Is it a Shaped Window ? Help ! */
469N/A if ((XShapeQueryExtents(mvDpy, win, &bdg, &xb, &yb, &wb, &hb,
469N/A &clp, &xc, &yc, &wc, &hc)) && bdg) {
469N/A
469N/A if ((wb == 0) || (hb == 0) || (wb > 2000) || (hb > 2000)) {
469N/A /* Empty shape, ignore it */
469N/A winList.used--;
469N/A return;
469N/A }
469N/A
469N/A isShaped = True;
469N/A pWinInfo->region = XCreateRegion();
469N/A rect = rects =
469N/A XShapeGetRectangles(mvDpy, win, ShapeBounding, &count, &ordering);
469N/A
469N/A while (count--) {
469N/A XUnionRectWithRegion(rect++, pWinInfo->region, pWinInfo->region);
469N/A }
469N/A if (rects != NULL) {
469N/A XFree((caddr_t)rects);
469N/A }
469N/A
469N/A tmpreg = XCreateRegion();
469N/A tmprct.x = pWinInfo->x; tmprct.y = pWinInfo->y;
469N/A tmprct.width = pWinInfo->width; tmprct.height = pWinInfo->height;
469N/A XUnionRectWithRegion(&tmprct, tmpreg, tmpreg);
469N/A XIntersectRegion(pWinInfo->region, tmpreg, pWinInfo->region);
469N/A XDestroyRegion(tmpreg);
469N/A }
469N/A if (ancestorShaped) {
469N/A /* make a local copy */
469N/A tmpancestorRegion = XCreateRegion();
469N/A XUnionRegion(tmpancestorRegion, ancestorRegion, tmpancestorRegion);
469N/A /* Translate from relative parent's origin to this window's origin */
469N/A XOffsetRegion(tmpancestorRegion, -(xwa.x + xwa.border_width),
469N/A -(xwa.y + xwa.border_width));
469N/A if (isShaped) { /* Compute effective bdg shape */
469N/A XIntersectRegion(tmpancestorRegion, pWinInfo->region, pWinInfo->region);
469N/A }
469N/A else {
469N/A pWinInfo->region = XCreateRegion();
469N/A XUnionRegion(tmpancestorRegion, pWinInfo->region, pWinInfo->region);
469N/A tmpreg = XCreateRegion();
469N/A tmprct.x = pWinInfo->x; tmprct.y = pWinInfo->y;
469N/A tmprct.width = pWinInfo->width; tmprct.height = pWinInfo->height;
469N/A XUnionRectWithRegion(&tmprct, tmpreg, tmpreg);
469N/A XIntersectRegion(pWinInfo->region, tmpreg, pWinInfo->region);
469N/A XDestroyRegion(tmpreg);
469N/A }
469N/A XDestroyRegion(tmpancestorRegion);
469N/A }
469N/A#endif /* SHAPE */
469N/A
469N/A /* Find children, back to front */
469N/A if (XQueryTree(mvDpy, win, &root, &parent, &children, &nchild)) {
469N/A
469N/A#ifdef SHAPE
469N/A tmpreg = pWinInfo->region;
469N/A#endif /* SHAPE */
469N/A
469N/A for (n=0; n<nchild; n++) {
469N/A#ifdef SHAPE
469N/A mvWalkTree(children[n], px+xwa.x+xwa.border_width,
469N/A py+xwa.y+xwa.border_width,
469N/A x1, y1, width, height, (ancestorShaped || isShaped),
469N/A tmpreg);
469N/A#else /* !SHAPE */
469N/A mvWalkTree(children[n], px+xwa.x+xwa.border_width,
469N/A py+xwa.y+xwa.border_width,
469N/A x1, y1, width, height);
469N/A#endif /* SHAPE */
469N/A }
469N/A /* free children */
469N/A if (nchild > 0)
469N/A XFree((caddr_t)children);
469N/A }
469N/A return;
469N/A}
469N/A
469N/A/*
469N/A * CHANGE
469N/A * Returns 0 if no problems,
469N/A * Returns 1 if depths differ
469N/A * returns 2 if colormap or visinfo differ
469N/A * NOTE that this chenge & the previous change are reprehensible hacks,
469N/A * to let xmag work with pageview, and xcolor respectively.
469N/A * USED TO BE...
469N/A * CHANGE
469N/A * Returns 0 if no problems,
469N/A * Returns 1 if visinfo or depth differ
469N/A * returns 2 if colormap only differ
469N/A * USED TO BE...
469N/A * Returns non-zero if the winList created by mvWalkTree
469N/A * might potentially have windows of different Visuals
469N/A * else returns 0
469N/A*/
469N/Aint
1233N/AmvIsMultiVis(void)
469N/A{
469N/A int retcode = 0;
469N/A int i = winList.used;
469N/A
469N/A while (i--) {
469N/A if(winList.wins[i].depth != winList.wins[0].depth)
469N/A return 1;
469N/A if (winList.wins[i].visinfo != winList.wins[0].visinfo)
469N/A retcode = 2;
469N/A if (winList.wins[i].colmap != winList.wins[0].colmap)
469N/A retcode = 2;
469N/A }
469N/A return retcode;
469N/A}
469N/A
469N/A/*
469N/A * Traverse the window list front to back. Get the entire Image
469N/A * from each window, but only Label a pixel in the Img once.
469N/A * That is, once a pixel has been Labeled, any more fetches
469N/A * from the same pixel position are discarded. Once all pixels
469N/A * positions have been fetched, we're done. This will eliminate
469N/A * windows that have nothing to contibute to the requested region,
469N/A * but will nevertheless have the problem of the painters
469N/A * algorithm, where more pixels were fetched from a
469N/A * window than were essential.
469N/A * Assumes that winList has been filled beforehand, and Img was cleared.
469N/A*/
469N/A
469N/Avoid
1233N/AmvDoWindowsFrontToBack(void)
469N/A{
469N/A int i;
469N/A MVWinVisInfo *pWI;
469N/A XImage *xim;
469N/A int xi, yi;
469N/A int nPixelsUnLabeled = request_width*request_height;
469N/A
469N/A for (i=winList.used-1; ((nPixelsUnLabeled > 0) && i >= 0); i--) {
469N/A pWI = &(winList.wins[i]);
469N/A if (!(xim = XGetImage(mvDpy, pWI->window, pWI->x, pWI->y, pWI->width,
469N/A pWI->height, (~0), ZPixmap))) {
469N/A return;
469N/A }
469N/A mvGetColormap(pWI);
469N/A /* For each pixel in the returned Image */
469N/A for (yi = 0; yi < pWI->height; yi++) {
469N/A#ifdef UPDATE_HACK
469N/A if ((yi % 128) == 0) {
469N/A (*mvCallbackFunction)(mvCallbackData);
469N/A }
469N/A#endif /* UPDATE_HACK */
469N/A for (xi = 0; xi < pWI->width; xi++) {
469N/A MVPel *pPel = mvFindPel(xi+pWI->x1-request_x, yi+pWI->y1-request_y);
469N/A /* If the pixel hasn't been labelled before */
469N/A if (!pPel->colmap) { /* pPel->colmap serves as a 'Label' */
469N/A /* label the pixel in the map with this window's cmap */
469N/A /*
469N/A * If Pixel value can be discarded, this is where
469N/A * you get the RGB value instead.
469N/A * Call a routine like mvFindColorInColormap() with the pixel
469N/A * value, and Colormap as parameters.
469N/A * The 'Label', instead of pPel->colmap could be a scratch bit ?
469N/A * But if its a full 32 bit pixel, and there are no
469N/A * free bits, you need to hang in extra bits somewhere.
469N/A * Maybe a bitmask associated with Img ?
469N/A */
469N/A#ifdef SHAPE
469N/A if (!(pWI->region) ||
469N/A (pWI->region && (XPointInRegion(pWI->region, xi+pWI->x, yi+pWI->y))
469N/A#ifdef XNEWS
469N/A && (XPointInRegion(pWI->region, xi+pWI->x+1, yi+pWI->y))
469N/A && (XPointInRegion(pWI->region, xi+pWI->x, yi+pWI->y+1))
469N/A && (XPointInRegion(pWI->region, xi+pWI->x+1, yi+pWI->y+1))
469N/A#endif /* XNEWS */
469N/A )
469N/A ) {
469N/A#endif /* SHAPE */
469N/A pPel->colmap = pWI->colmap;
469N/A /* and pixel value */
469N/A pPel->pixel = XGetPixel(xim, xi, yi);
469N/A nPixelsUnLabeled--;
469N/A#ifdef SHAPE
469N/A }
469N/A#endif /* SHAPE */
469N/A }
469N/A }
469N/A }
469N/A /* free image */
469N/A XDestroyImage(xim);
469N/A }
469N/A}
469N/A
469N/A/*
469N/A * Get all the colors from this window's colormap.
469N/A * That's slightly complicated when we hit
469N/A * a true color or direct color visual.
469N/A * Assumes that a global list of colmaps is present, and
469N/A * that the Colors field was NULLed beforehand.
469N/A*/
469N/A
469N/Astatic void
1233N/AmvGetColormap(MVWinVisInfo *pWI)
469N/A{
469N/A if (!pWI->colmap->Colors) { /* This is the first time we're visiting */
469N/A MVColmap *pCmp = pWI->colmap;
469N/A XVisualInfo *pVis = pWI->visinfo;
469N/A XColor *pCol;
469N/A int size = pVis->colormap_size;
469N/A
469N/A /* Allocate enough memory */
469N/A pCmp->Colors = pCol = (XColor *)calloc((sizeof(XColor)), size);
469N/A if (pVis->class == TrueColor || pVis->class == DirectColor) {
469N/A unsigned long i;
469N/A /* We have to create a composite pixel value */
469N/A mvCalculateComposite(pWI);
469N/A for (i = 0; i < (unsigned long)(size);i++, pCol++) {
469N/A pCol->pixel = mvCompositePixel(i, pCmp);
469N/A }
469N/A }
469N/A else {
469N/A unsigned long i;
469N/A /* Fill in the pixel values by hand */
469N/A for (i = 0; i < (unsigned long)(size);) {
469N/A pCol++->pixel = i++;
469N/A }
469N/A }
469N/A XQueryColors(mvDpy, pCmp->cmap, pCmp->Colors, size);
469N/A }
469N/A}
469N/A
469N/A/*
469N/A * Given a VisualID, return a pointer to the VisualInfo structure.
469N/A * Assumes that a global mvVlist for this screen has already
469N/A * been created. Uses globals mvNumVis, and mvVlist.
469N/A * Returns NULL if the vid is not matched.
469N/A*/
469N/Astatic XVisualInfo *
1233N/AmvMatchVisual(VisualID vid)
469N/A{
469N/A XVisualInfo *pVis = mvVlist;
469N/A while (pVis < (mvVlist+mvNumVis)) {
469N/A if (vid == pVis->visualid) {
469N/A return pVis;
469N/A }
469N/A pVis++;
469N/A }
469N/A return NULL;
469N/A}
469N/A
469N/A/*
469N/A * Calculate a composite pixel value that indexes into all
469N/A * three primaries . Assumes Composite Calcs have been performed
469N/A * already on the colmap.
469N/A*/
469N/Astatic unsigned long
1233N/AmvCompositePixel(unsigned long i, MVColmap *pCmp)
469N/A{
469N/A unsigned long val = 0;
469N/A
469N/A if (i < pCmp->rmax) val |= i << pCmp->rshft;
469N/A if (i < pCmp->gmax) val |= i << pCmp->gshft;
469N/A if (i < pCmp->bmax) val |= i << pCmp->bshft;
469N/A return val;
469N/A}
469N/A
469N/A/*
469N/A * Calculate the offsets used to composite a pixel value for
469N/A * the TrueColor & DirectColor cases
469N/A * Assumes its called only on a True or DirectColor visual.
469N/A*/
469N/Astatic void
1233N/AmvCalculateComposite(MVWinVisInfo *pWI)
469N/A{
469N/A MVColmap *pCmp = pWI->colmap;
469N/A XVisualInfo *pVis = pWI->visinfo;
469N/A /* Check if this has been done before */
469N/A if (!pCmp->doComposite) {
469N/A pCmp->doComposite = True;
469N/A /* These are the sizes of each primary map ... */
469N/A pCmp->red_mask = pVis->red_mask;
469N/A pCmp->green_mask = pVis->green_mask;
469N/A pCmp->blue_mask = pVis->blue_mask;
469N/A pCmp->rmax = 1 << mvOnes(pVis->red_mask);
469N/A pCmp->gmax = 1 << mvOnes(pVis->green_mask);
469N/A pCmp->bmax = 1 << mvOnes(pVis->blue_mask);
469N/A pCmp->rshft = mvShifts(pVis->red_mask);
469N/A pCmp->gshft = mvShifts(pVis->green_mask);
469N/A pCmp->bshft = mvShifts(pVis->blue_mask);
469N/A pCmp->rgbshft = (16 - pVis->bits_per_rgb);
469N/A }
469N/A}
469N/A
469N/A/*
469N/A * Calculate number of 1 bits in mask
469N/A * Classic hack not written by this author.
469N/A*/
469N/Aint
1233N/AmvOnes(unsigned long mask)
469N/A{
469N/A unsigned long y;
469N/A
469N/A y = (mask >> 1) &033333333333;
469N/A y = mask - y - ((y >> 1) & 033333333333);
469N/A return (((y + (y >> 3)) & 030707070707) % 077);
469N/A}
469N/A
469N/A/*
469N/A * Calculate the number of shifts till we hit the mask
469N/A*/
469N/Aint
1233N/AmvShifts(unsigned long mask)
469N/A{
469N/A int y = 0;
469N/A
469N/A if (mask) {
469N/A while(!(mask&0x1)) {
469N/A mask = mask >> 1;
469N/A y++;
469N/A }
469N/A }
469N/A return y;
469N/A}
469N/A
469N/A/*
469N/A * find & creat a colmap struct for this cmap
469N/A * Assumes that colMaps was cleared before the first time
469N/A * it is called.
469N/A*/
469N/Astatic MVColmap *
1233N/AmvFindColormap(Colormap cmap)
469N/A{
469N/A MVColmap *pCmap;
469N/A /* if we've seen this cmap before, return its struct colmap */
469N/A for (pCmap = colMaps; pCmap; pCmap = pCmap->next) {
469N/A if (cmap == pCmap->cmap)
469N/A return pCmap;
469N/A }
469N/A /* First time for this cmap, creat & link */
469N/A pCmap = (MVColmap *) calloc(sizeof(MVColmap), 1);
469N/A pCmap->next = colMaps;
469N/A pCmap->cmap = cmap;
469N/A colMaps = pCmap;
469N/A return pCmap;
469N/A}
469N/A
469N/A/*
469N/A * Use pixel value at x, y as an index into
469N/A * the colmap's list of Colors.
469N/A * If the pixel value were not important, this would be called
469N/A * in mvDoWindowsFrontToBack(), with the pixel value
469N/A * and colmap as parameters, to get RGB values directly.
469N/A*/
469N/AXColor *
1233N/AmvFindColorInColormap(int x, int y)
469N/A{
469N/A MVPel *pPel = mvFindPel(x, y);
469N/A MVColmap *pCmap = pPel->colmap;
469N/A static XColor scratch;
469N/A
469N/A if (pCmap->doComposite) { /* This is either True or DirectColor */
469N/A /* Treat the pixel value as 3 separate indices, composite
469N/A the color into scratch, return a pointer to scratch */
469N/A unsigned long pix = pPel->pixel;
469N/A unsigned long index = (pix & pCmap->red_mask) >> pCmap->rshft;
469N/A scratch.red=pCmap->Colors[(pix & pCmap->red_mask)>>pCmap->rshft].red;
469N/A scratch.green=pCmap->Colors[(pix & pCmap->green_mask)>>pCmap->gshft].green;
469N/A scratch.blue=pCmap->Colors[(pix & pCmap->blue_mask)>>pCmap->bshft].blue;
469N/A scratch.pixel=pix;
469N/A return(&scratch);
469N/A }
469N/A else { /* This is simple */
469N/A return &(pCmap->Colors[pPel->pixel]);
469N/A }
469N/A}