next up previous
Next: About this document Up: Manipulation de Palettes de Previous: Remarques sur XAllocColorCells

Code source du programme d'essai

Ce programme reprend en grande partie la méthode utilisé dans Xspect. Cette-à-dire qu'il essaie d'allouer les couleurs dans la palette courante, et en cas d'échec il crée une palette virtuelle. Pour tester, les résultats, nous affichons une mire des couleurs.

/* INCLUDES */
/* -------- */

/* standard */
#include <stdio.h>
#include <stdlib.h>

/* XLib	*/
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>

/* MOTIF */
#include <Xm/FileSB.h>
#include <Xm/DrawingA.h>
#include <Xm/PushBG.h>
#include <Xm/RowColumn.h>

/* DEFINES */
/* ------- */
#define charset XmSTRING_DEFAULT_CHARSET
#define MAX_PLANE           2
#define MAX_CELL            ((MAX_COLOR) * (1 << (MAX_PLANE)))
#define MAX_COLOR           16
#define CANNOT_OVERLAY      0
#define CAN_OVERLAY         1
#define MAX_CHAR            256
#define UNDEFINED           -1
#define WIDTH		    400
#define HEIGHT		    300

/* TYPES */
/* ----- */
typedef char STRING[MAX_CHAR];

/* Constantes de couleurs */
/* ---------------------- */
static short valStd8[][3] =
{
  0xFF, 0xFF, 0xFF,
  0x00, 0xFF, 0xFF,
  0xFF, 0x00, 0xFF,
  0x00, 0x00, 0xFF,
  0xFF, 0xFF, 0x00,
  0x00, 0xFF, 0x00,
  0xFF, 0x00, 0x00,
  0x00, 0x00, 0x00
};


/* Variables globales */
/* ------------------ */
Display *display;
int screen_num;
Window window;
unsigned long planeMasks[MAX_PLANE];
unsigned long pixels[MAX_COLOR];
XColor exactDefs[MAX_CELL];

Colormap colormap, mycolormap;
int iwhite = UNDEFINED;
int iblack = UNDEFINED;
int ifg = UNDEFINED;
int ibg = UNDEFINED;
Pixmap pixmap;



void blkToZero(str)
  char *str;
{
  int i; 
  char *ptr = str;
  
  for (i = 0; i < strlen(str); i++, ptr++)
    {
      if (*ptr == ' ')
	*ptr = '0';
    }
}

void fin()
{
  /* Restore the old colormap */
  if (mycolormap!=colormap)
    {
      printf("Restore the old colormap\n");
      XFreeColormap(display,mycolormap);
    }

  exit();
}


/* Programme Principal */
/* ------------------- */
main(argc,argv)
int argc;
char *argv[];
{
  Widget	topLevel,text_w, dialog,drawing_a, pb;
  XtAppContext	app;
  XGCValues gcv;
  GC gc;

  extern void	exit(), echo_file();
  void DessinePalette();
  void initColors();
  void drawing_area_callback();
 
  topLevel=XtVaAppInitialize(&app, "Demos", NULL, 0, 
     &argc, argv, NULL,
     XmNwidth, WIDTH,
     XmNheight, HEIGHT,
     NULL);

  display = XtDisplay(topLevel);
  screen_num = DefaultScreen(display);
  window=XtWindow(topLevel);

  initColors(8);
  XtVaSetValues(topLevel,XmNcolormap,mycolormap,NULL);

  /* Create a drawing area widget */
  drawing_a=XtVaCreateWidget("drawing_a",
    xmDrawingAreaWidgetClass, topLevel,
    NULL);
  XtAddCallback(drawing_a,XmNexposeCallback,drawing_area_callback,NULL);

  gc = XCreateGC(XtDisplay(drawing_a),
		  RootWindowOfScreen(XtScreen(drawing_a)), 0, NULL);
  XtVaSetValues(drawing_a,XmNuserData,gc,NULL);

  /* Create a pixmap the same size as the drawing area */
  pixmap=XCreatePixmap(XtDisplay(drawing_a),
		       RootWindowOfScreen(XtScreen(drawing_a)),WIDTH,HEIGHT,
		       DefaultDepthOfScreen(XtScreen(drawing_a)));

  
  /* Clear pixmap with white */
  XSetForeground(XtDisplay(drawing_a), gc, WhitePixelOfScreen(XtScreen(drawing_a)));
  XFillRectangle(XtDisplay(drawing_a), pixmap,gc,0,0,WIDTH,HEIGHT);


  DessinePalette(drawing_a);


  /* Add a pushbutton the user can use to close */
  pb = XtVaCreateManagedWidget("Close",
			       xmPushButtonGadgetClass, drawing_a,
			       NULL);

  /* if activated call the callback */
  XtAddCallback(pb,XmNactivateCallback, fin,NULL);

  /* create a file selection dialog */
  dialog=XmCreateFileSelectionDialog(topLevel,"filesb",NULL,0);
  XtAddCallback(dialog,XmNcancelCallback,exit,NULL); 
  XtAddCallback(dialog,XmNokCallback,echo_file,NULL); 
  
  XtManageChild(dialog); 

  /* main loop */
  XtManageChild(drawing_a);
  XtRealizeWidget(topLevel);
  XtAppMainLoop(app);

}


/* Fonction Callback appelee lors de l'activation de la fenetre */
/* ou de sa re-exposition					*/
/* ------------------------------------------------------------ */
void drawing_area_callback(widget,data,cbs)
Widget widget;
XtPointer data;
XmDrawingAreaCallbackStruct *cbs;
{
  XEvent *event=cbs->event;
  Display *dpy=event->xany.display;

  if (cbs->reason == XmCR_EXPOSE || cbs->reason == XmCR_ACTIVATE)
    {
      GC gc;
      XtVaGetValues(widget,XmNuserData,&gc,NULL);
      XCopyArea(dpy,pixmap, event->xany.window,gc,0,0,WIDTH,HEIGHT,0,0);
    }
}


/* Write the name of the selected file on the screen */
/* ------------------------------------------------- */
void echo_file(fs,client_data,cbs)
Widget fs; /* file selection box */
XtPointer client_data;
XmFileSelectionBoxCallbackStruct *cbs;
{
  char *filename;

  if (!XmStringGetLtoR(cbs->value,charset,&filename))
    return;

  if (!*filename)
    {
      printf("No file selected.");
      XtFree(filename);
      return;
    }

  printf("Filename given : %s \n",filename);
  XtFree(filename);
}



/* Draw the colormap in a window */
/* ----------------------------- */
void DessinePalette(widget)
Widget widget;
{
  int i;
  int step = (4 * WIDTH / 5) / MAX_COLOR;
  GC gc;

  XtVaGetValues(widget,XmNuserData,&gc,NULL);

  for (i=0;i<MAX_COLOR;i++)
    {
      XSetForeground(XtDisplay(widget), gc, exactDefs[i].pixel);      
      XFillRectangle(XtDisplay(widget),pixmap,gc,i*step,0,step,HEIGHT);
    }
}


/* colormap initialisation */
/* ----------------------- */
void initColors(ncolor)
int ncolor;
{
  XVisualInfo visualInfo;
  int defaultDepth=DefaultDepth(display,screen_num);

  int nplane, ncell;

  colormap = DefaultColormap(display,screen_num);
  mycolormap=colormap;

  nplane = 2;
  ncell = ncolor * (1 << nplane);

  if (defaultDepth == 1) 
    {
      /* must be StaticGray, use black and white */
      printf("The screen can only have 2 colors.");

      ncolor = 0;
      nplane = 2;
      ncell = 2;
    }
  
  if (!XMatchVisualInfo(display, screen_num, defaultDepth, PseudoColor, &visualInfo)) 
    {  
      if (!XMatchVisualInfo(display, screen_num, defaultDepth, DirectColor, &visualInfo)) 
	{
	  /* No PseudoColor or TrueColor visual available at defaultDepth.
	   * Some applications might try for a GrayScale visual 
	   * here if they can use gray to advantage, before 
	   * giving up and using black and white.
	   */
	  printf("initColors: TODO HERE: try for a GrayScale... \n");
	}
    }

  if ( getColors(ncolor, nplane, ncell, &planeMasks[0], &pixels[0], &exactDefs[0]) == CANNOT_OVERLAY )
      printf("We can't allocate enough colors for overlay.\n");
}

int getColors(maxColors, maxPlanes, maxCells, planeMasks, pixels, exactDefs)
     int maxColors;
     int maxPlanes;
     int maxCells;
     unsigned long planeMasks[MAX_PLANE];
     unsigned long pixels[MAX_COLOR];
     XColor exactDefs[MAX_CELL];
{
  STRING name[MAX_CELL];
  XColor *pExDef;
  Colormap defaultCmap = colormap;
  int nbCells = maxCells;
  int power2maxPlanes;
  int i, j, k;
  int class;

  void createPrivateMap();
  
  /* compute our private color map */
  createPrivateMap(&valStd8[0][0], name, maxColors, maxPlanes, maxCells, planeMasks, pixels, exactDefs);
  iwhite = 0;
  ibg = 1; /* cyan */
  iblack = 7;
  ifg = 3; /* blue */

  if (XAllocColorCells(display, defaultCmap, False, planeMasks, maxPlanes, pixels, maxColors) == 0) 
    {
      fprintf(stderr,"Can't alloc enough colors in the current color map. Creation of a new one. \n");
      
      if ((defaultCmap=XCopyColormapAndFree(display,colormap)) == BadAlloc)
	fprintf(stderr, "\nCan't Create new colormap\n");

      if (XAllocColorCells(display, defaultCmap, False, planeMasks, maxPlanes, pixels, maxColors) == 0)  
	{
	  fprintf(stderr,"\nCan't allocate %d colors after created the new color map\n\
                          This is a big problem !\n",maxColors);
	  exit(0);
	}
    }
  
  /* allocated colorcells succesfully,
   * now set their colors
   */

  for (i = 0; i < maxCells; i++)
    {
      exactDefs[i].flags = DoRed | DoGreen | DoBlue;
      if (! XParseColor(display, defaultCmap, name[i],  &exactDefs[i])) 
	  fprintf(stderr,"basic: color name %s not in database", name[i]);

      printf("%s\n",name[i]);
    }

  /* set pixel value in struct to the allocated ones */
  for (i = 0; i < (1 << maxPlanes); i++)
    for (j = 0; j < maxColors; j++)
      {
	unsigned long msk = 0;
	
	for (k = 0; k < maxPlanes; k++)
	  {
	    int bool = ((1 << k) & i) >> k;
	    msk |= bool * planeMasks[k];
	  }
	
	exactDefs[i * maxColors + j].pixel = pixels[j] | msk;
      }
  
  /* this sets the color of the read/write cells */
  XStoreColors(display, defaultCmap, exactDefs, nbCells);

  if (defaultCmap!=colormap)
    {
       mycolormap=defaultCmap;
       XInstallColormap(display,mycolormap);
    }

  if (nbCells >= 4) 
       return (CAN_OVERLAY);
   else 
       return (CANNOT_OVERLAY);
}





void createPrivateMap(val, name, maxColors, maxPlanes, maxCells, planeMasks, pixels, exactDefs)
     short val[][3];
     STRING name[MAX_CELL];
     int maxColors;
     int maxPlanes;
     int maxCells;
     unsigned long planeMasks[MAX_PLANE];
     unsigned long pixels[MAX_COLOR];
     XColor exactDefs[MAX_CELL];
{
  int i, j;
  int fr1, fg1, fb1;
  int fr2, fg2, fb2;
  int fr3, fg3, fb3;
  double coeff = 1.5;
  
  printf("createPrivateMap..\n");

  /* plan 1 */
  fr1 = 0;
  fg1 = 255;
  fb1 = 0;

  /* plan 2 */
  fr2 = 255;
  fg2 = 0;
  fb2 = 0;

  /* plan 1 & 2 */
  fr3 = 255;
  fg3 = 255;
  fb3 = 0;

  i = 0;
  for (j = 0; j < maxColors; j++)
      {
	sprintf(name[i * maxColors + j], "#%2X%2X%2X\0", val[j][0],  val[j][1],  val[j][2]);
	blkToZero(name[i * maxColors + j]);
      }
  
  i = 1;
  for (j = 0; j < maxColors; j++)
      {
	double cr, cg, cb;

	cr = (coeff * val[j][0] + fr1) / (coeff + 1.);
	cg = (coeff * val[j][1] + fg1) / (coeff + 1.);
	cb = (coeff * val[j][2] + fb1) / (coeff + 1.);

	if (cr > 255.) cr = 255.;
	if (cg > 255.) cg = 255.;
	if (cb > 255.) cb = 255.;
	sprintf(name[i * maxColors + j], "#%2X%2X%2X\0", (int) cr, (int) cg, (int) cb);
	blkToZero(name[i * maxColors + j]);
      }
  
  i = 2;
  for (j = 0; j < maxColors; j++)
      {
	double cr, cg, cb;

	cr = (coeff * val[j][0] + fr2) / (coeff + 1.);
	cg = (coeff * val[j][1] + fg2) / (coeff + 1.);
	cb = (coeff * val[j][2] + fb2) / (coeff + 1.);

	if (cr > 255.) cr = 255.;
	if (cg > 255.) cg = 255.;
	if (cb > 255.) cb = 255.;
	sprintf(name[i * maxColors + j], "#%2X%2X%2X\0", (int) cr, (int) cg, (int) cb);
	blkToZero(name[i * maxColors + j]);
      }
  
  i = 3;
  for (j = 0; j < maxColors; j++)
      {
	double cr, cg, cb;

	cr = (coeff * val[j][0] + fr3) / (coeff + 1.);
	cg = (coeff * val[j][1] + fg3) / (coeff + 1.);
	cb = (coeff * val[j][2] + fb3) / (coeff + 1.); 

	if (cr > 255.) cr = 255.;
	if (cg > 255.) cg = 255.;
	if (cb > 255.) cb = 255.;
	sprintf(name[i * maxColors + j], "#%2X%2X%2X\0", (int) cr, (int) cg, (int) cb);
	blkToZero(name[i * maxColors + j]);

      }
}



Gauthier Lebrun
Fri Apr 18 17:58:46 MET DST 1997