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]);
}
}