Actual source code: xcolor.c
2: /*
3: Code for managing color the X implementation of the PetscDraw routines.
5: Currently we default to using cmapping[0 to PETSC_DRAW_BASIC_COLORS-1] for the basic colors and
6: cmapping[DRAW_BASIC_COLORS to 255] for contour plots.
8: */
9: #include <../src/sys/classes/draw/impls/x/ximpl.h>
10: #include <X11/Xatom.h>
12: static const char *colornames[PETSC_DRAW_BASIC_COLORS] = {"white", "black", "red", "green", "cyan", "blue", "magenta", "aquamarine", "forestgreen", "orange", "violet",
13: "brown", "pink", "coral", "gray", "yellow", "gold", "lightpink", "mediumturquoise", "khaki", "dimgray", "yellowgreen",
14: "skyblue", "darkgreen", "navyblue", "sandybrown", "cadetblue", "powderblue", "deeppink", "thistle", "limegreen", "lavenderblush", "plum"};
16: /*
17: Sets up a color map for a display. This is shared by all the windows
18: opened on that display; this is to save time when windows are open so
19: each one does not have to create its own color map which can take 15 to 20 seconds
21: This is new code written 2/26/1999 Barry Smith,I hope it can replace
22: some older,rather confusing code.
24: The calls to XAllocNamedColor() and XAllocColor() are very slow
25: because we have to request from the X server for each
26: color. Could not figure out a way to request a large number at the
27: same time.
29: IMPORTANT: this code will fail if user opens windows on two different
30: displays: should add error checking to detect this. This is because all windows
31: share the same gColormap and gCmapping.
33: */
34: static Colormap gColormap = 0;
35: static PetscDrawXiPixVal gCmapping[PETSC_DRAW_MAXCOLOR];
36: static unsigned char gCpalette[PETSC_DRAW_MAXCOLOR][3];
38: PetscErrorCode PetscDrawSetUpColormap_Shared(Display *display, int screen, Visual *visual, Colormap colormap)
39: {
40: int i, k, ncolors = PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS;
41: unsigned char R[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
42: unsigned char G[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
43: unsigned char B[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
44: XColor colordef, ecolordef;
45: PetscBool fast = PETSC_FALSE;
47: PetscFunctionBegin;
48: if (colormap) gColormap = colormap;
49: else gColormap = DefaultColormap(display, screen);
51: /* set the basic colors into the color map */
52: for (i = 0; i < PETSC_DRAW_BASIC_COLORS; i++) {
53: XAllocNamedColor(display, gColormap, colornames[i], &colordef, &ecolordef);
54: gCmapping[i] = colordef.pixel;
55: gCpalette[i][0] = (unsigned char)(colordef.red >> 8);
56: gCpalette[i][1] = (unsigned char)(colordef.green >> 8);
57: gCpalette[i][2] = (unsigned char)(colordef.blue >> 8);
58: }
60: /* set the contour colors into the colormap */
61: PetscCall(PetscOptionsGetBool(NULL, NULL, "-draw_fast", &fast, NULL));
62: PetscCall(PetscDrawUtilitySetCmap(NULL, ncolors, R, G, B));
63: for (i = 0, k = PETSC_DRAW_BASIC_COLORS; i < ncolors; i++, k++) {
64: colordef.red = (unsigned short)(R[i] << 8);
65: colordef.green = (unsigned short)(G[i] << 8);
66: colordef.blue = (unsigned short)(B[i] << 8);
67: colordef.flags = DoRed | DoGreen | DoBlue;
68: colordef.pixel = gCmapping[PETSC_DRAW_BLACK];
69: if (!fast) XAllocColor(display, gColormap, &colordef);
70: gCmapping[k] = colordef.pixel;
71: gCpalette[k][0] = R[i];
72: gCpalette[k][1] = G[i];
73: gCpalette[k][2] = B[i];
74: }
76: PetscCall(PetscInfo(NULL, "Successfully allocated colors\n"));
77: PetscFunctionReturn(PETSC_SUCCESS);
78: }
80: /*
81: Keep a record of which pixel numbers in the cmap have been
82: used so far; this is to allow us to try to reuse as much of the current
83: colormap as possible.
84: */
85: static PetscBool cmap_pixvalues_used[PETSC_DRAW_MAXCOLOR];
86: static int cmap_base = 0;
88: PetscErrorCode PetscDrawSetUpColormap_Private(Display *display, int screen, Visual *visual, Colormap colormap)
89: {
90: int found, i, k, ncolors = PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS;
91: unsigned char R[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
92: unsigned char G[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
93: unsigned char B[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
94: Colormap defaultmap = DefaultColormap(display, screen);
95: XColor colordef;
96: PetscBool fast = PETSC_FALSE;
98: PetscFunctionBegin;
99: if (colormap) gColormap = colormap;
100: else gColormap = XCreateColormap(display, RootWindow(display, screen), visual, AllocAll);
102: cmap_base = 0;
104: PetscCall(PetscMemzero(cmap_pixvalues_used, sizeof(cmap_pixvalues_used)));
106: /* set the basic colors into the color map */
107: for (i = 0; i < PETSC_DRAW_BASIC_COLORS; i++) {
108: XParseColor(display, gColormap, colornames[i], &colordef);
109: /* try to allocate the color in the default-map */
110: found = XAllocColor(display, defaultmap, &colordef);
111: /* use it, if it it exists and is not already used in the new colormap */
112: if (found && colordef.pixel < PETSC_DRAW_MAXCOLOR && !cmap_pixvalues_used[colordef.pixel]) {
113: cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
114: /* otherwise search for the next available slot */
115: } else {
116: while (cmap_pixvalues_used[cmap_base]) cmap_base++;
117: colordef.pixel = cmap_base;
118: cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
119: }
120: XStoreColor(display, gColormap, &colordef);
121: gCmapping[i] = colordef.pixel;
122: gCpalette[i][0] = (unsigned char)(colordef.red >> 8);
123: gCpalette[i][1] = (unsigned char)(colordef.green >> 8);
124: gCpalette[i][2] = (unsigned char)(colordef.blue >> 8);
125: }
127: /* set the contour colors into the colormap */
128: PetscCall(PetscOptionsGetBool(NULL, NULL, "-draw_fast", &fast, NULL));
129: PetscCall(PetscDrawUtilitySetCmap(NULL, ncolors, R, G, B));
130: for (i = 0, k = PETSC_DRAW_BASIC_COLORS; i < ncolors; i++, k++) {
131: colordef.red = (unsigned short)(R[i] << 8);
132: colordef.green = (unsigned short)(G[i] << 8);
133: colordef.blue = (unsigned short)(B[i] << 8);
134: colordef.flags = DoRed | DoGreen | DoBlue;
135: colordef.pixel = gCmapping[PETSC_DRAW_BLACK];
136: if (!fast) {
137: /* try to allocate the color in the default-map */
138: found = XAllocColor(display, defaultmap, &colordef);
139: /* use it, if it it exists and is not already used in the new colormap */
140: if (found && colordef.pixel < PETSC_DRAW_MAXCOLOR && !cmap_pixvalues_used[colordef.pixel]) {
141: cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
142: /* otherwise search for the next available slot */
143: } else {
144: while (cmap_pixvalues_used[cmap_base]) cmap_base++;
145: colordef.pixel = cmap_base;
146: cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
147: }
148: XStoreColor(display, gColormap, &colordef);
149: }
150: gCmapping[k] = colordef.pixel;
151: gCpalette[k][0] = R[i];
152: gCpalette[k][1] = G[i];
153: gCpalette[k][2] = B[i];
154: }
156: PetscCall(PetscInfo(NULL, "Successfully allocated colors\n"));
157: PetscFunctionReturn(PETSC_SUCCESS);
158: }
160: PetscErrorCode PetscDrawSetUpColormap_X(Display *display, int screen, Visual *visual, Colormap colormap)
161: {
162: PetscBool sharedcolormap = PETSC_FALSE;
163: XVisualInfo vinfo;
165: PetscFunctionBegin;
166: PetscCall(PetscOptionsGetBool(NULL, NULL, "-draw_x_shared_colormap", &sharedcolormap, NULL));
167: /*
168: Need to determine if window supports allocating a private colormap,
169: */
170: if (XMatchVisualInfo(display, screen, 24, StaticColor, &vinfo) || XMatchVisualInfo(display, screen, 24, TrueColor, &vinfo) || XMatchVisualInfo(display, screen, 16, StaticColor, &vinfo) || XMatchVisualInfo(display, screen, 16, TrueColor, &vinfo) || XMatchVisualInfo(display, screen, 15, StaticColor, &vinfo) || XMatchVisualInfo(display, screen, 15, TrueColor, &vinfo))
171: sharedcolormap = PETSC_TRUE;
172: /*
173: Generate the X colormap object
174: */
175: if (sharedcolormap) {
176: PetscCall(PetscDrawSetUpColormap_Shared(display, screen, visual, colormap));
177: } else {
178: PetscCall(PetscDrawSetUpColormap_Private(display, screen, visual, colormap));
179: }
180: PetscFunctionReturn(PETSC_SUCCESS);
181: }
183: PETSC_INTERN PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *, Colormap);
185: PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *XiWin, Colormap colormap)
186: {
187: PetscBool fast = PETSC_FALSE;
189: PetscFunctionBegin;
190: PetscCall(PetscOptionsGetBool(NULL, NULL, "-draw_fast", &fast, NULL));
191: PetscCheck(XiWin->depth >= 8, PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "PETSc Graphics require monitors with at least 8 bit color (256 colors)");
192: if (!gColormap) PetscCall(PetscDrawSetUpColormap_X(XiWin->disp, XiWin->screen, XiWin->vis, colormap));
193: XiWin->cmap = gColormap;
194: XiWin->cmapsize = fast ? PETSC_DRAW_BASIC_COLORS : PETSC_DRAW_MAXCOLOR;
195: PetscCall(PetscMemcpy(XiWin->cmapping, gCmapping, sizeof(XiWin->cmapping)));
196: PetscCall(PetscMemcpy(XiWin->cpalette, gCpalette, sizeof(XiWin->cpalette)));
197: XiWin->background = XiWin->cmapping[PETSC_DRAW_WHITE];
198: XiWin->foreground = XiWin->cmapping[PETSC_DRAW_BLACK];
199: PetscFunctionReturn(PETSC_SUCCESS);
200: }
202: PetscErrorCode PetscDrawXiColormap(PetscDraw_X *XiWin)
203: {
204: return PetscDrawSetColormap_X(XiWin, (Colormap)0);
205: }
207: /*
208: Color in X is many-layered. The first layer is the "visual",a
209: immutable attribute of a window set when the window is
210: created.
212: The next layer is the colormap. The installation of colormaps is
213: the business of the window manager (in some distant later release).
214: */
216: /*
217: This routine gets the visual class (PseudoColor, etc) and returns
218: it. It finds the default visual. Possible returns are
219: PseudoColor
220: StaticColor
221: DirectColor
222: TrueColor
223: GrayScale
224: StaticGray
225: */
226: PetscErrorCode PetscDrawXiSetVisualClass(PetscDraw_X *XiWin)
227: {
228: XVisualInfo vinfo;
230: PetscFunctionBegin;
231: if (XMatchVisualInfo(XiWin->disp, XiWin->screen, 24, DirectColor, &vinfo)) {
232: XiWin->vis = vinfo.visual;
233: } else if (XMatchVisualInfo(XiWin->disp, XiWin->screen, 8, PseudoColor, &vinfo)) {
234: XiWin->vis = vinfo.visual;
235: } else if (XMatchVisualInfo(XiWin->disp, XiWin->screen, DefaultDepth(XiWin->disp, XiWin->screen), PseudoColor, &vinfo)) {
236: XiWin->vis = vinfo.visual;
237: } else {
238: XiWin->vis = DefaultVisual(XiWin->disp, XiWin->screen);
239: }
240: PetscFunctionReturn(PETSC_SUCCESS);
241: }
243: PetscErrorCode PetscDrawXiSetColormap(PetscDraw_X *XiWin)
244: {
245: PetscFunctionBegin;
246: XSetWindowColormap(XiWin->disp, XiWin->win, XiWin->cmap);
247: PetscFunctionReturn(PETSC_SUCCESS);
248: }
250: /*
251: Get RGB color entries out of the X colormap
252: */
253: PetscErrorCode PetscDrawXiGetPalette(PetscDraw_X *XiWin, unsigned char palette[PETSC_DRAW_MAXCOLOR][3])
254: {
255: int k;
256: XColor colordef[PETSC_DRAW_MAXCOLOR];
258: PetscFunctionBegin;
259: for (k = 0; k < PETSC_DRAW_MAXCOLOR; k++) {
260: colordef[k].pixel = XiWin->cmapping[k];
261: colordef[k].flags = DoRed | DoGreen | DoBlue;
262: }
263: XQueryColors(XiWin->disp, XiWin->cmap, colordef, PETSC_DRAW_MAXCOLOR);
264: for (k = 0; k < PETSC_DRAW_MAXCOLOR; k++) {
265: palette[k][0] = (unsigned char)(colordef[k].red >> 8);
266: palette[k][1] = (unsigned char)(colordef[k].green >> 8);
267: palette[k][2] = (unsigned char)(colordef[k].blue >> 8);
268: }
269: PetscFunctionReturn(PETSC_SUCCESS);
270: }