Actual source code: xcolor.c
1: /*
2: Code for managing color the X implementation of the PetscDraw routines.
4: Currently we default to using cmapping[0 to PETSC_DRAW_BASIC_COLORS-1] for the basic colors and
5: cmapping[DRAW_BASIC_COLORS to 255] for contour plots.
7: */
8: #include <../src/sys/classes/draw/impls/x/ximpl.h>
9: #include <X11/Xatom.h>
11: static const char *colornames[PETSC_DRAW_BASIC_COLORS] = {"white", "black", "red", "green", "cyan", "blue", "magenta", "aquamarine", "forestgreen", "orange", "violet",
12: "brown", "pink", "coral", "gray", "yellow", "gold", "lightpink", "mediumturquoise", "khaki", "dimgray", "yellowgreen",
13: "skyblue", "darkgreen", "navyblue", "sandybrown", "cadetblue", "powderblue", "deeppink", "thistle", "limegreen", "lavenderblush", "plum"};
15: /*
16: Sets up a color map for a display. This is shared by all the windows
17: opened on that display; this is to save time when windows are open so
18: each one does not have to create its own color map which can take 15 to 20 seconds
20: This is new code written 2/26/1999 Barry Smith,I hope it can replace
21: some older,rather confusing code.
23: The calls to XAllocNamedColor() and XAllocColor() are very slow
24: because we have to request from the X server for each
25: color. Could not figure out a way to request a large number at the
26: same time.
28: IMPORTANT: this code will fail if user opens windows on two different
29: displays: should add error checking to detect this. This is because all windows
30: share the same gColormap and gCmapping.
32: */
33: static Colormap gColormap = 0;
34: static PetscDrawXiPixVal gCmapping[PETSC_DRAW_MAXCOLOR];
35: static unsigned char gCpalette[PETSC_DRAW_MAXCOLOR][3];
37: static PetscErrorCode PetscDrawSetUpColormap_Shared(Display *display, int screen, Visual *visual, Colormap colormap)
38: {
39: int i, k, ncolors = PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS;
40: unsigned char R[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
41: unsigned char G[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
42: unsigned char B[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
43: XColor colordef, ecolordef;
44: PetscBool fast = PETSC_FALSE;
46: PetscFunctionBegin;
47: if (colormap) gColormap = colormap;
48: else gColormap = DefaultColormap(display, screen);
50: /* set the basic colors into the color map */
51: for (i = 0; i < PETSC_DRAW_BASIC_COLORS; i++) {
52: XAllocNamedColor(display, gColormap, colornames[i], &colordef, &ecolordef);
53: gCmapping[i] = colordef.pixel;
54: gCpalette[i][0] = (unsigned char)(colordef.red >> 8);
55: gCpalette[i][1] = (unsigned char)(colordef.green >> 8);
56: gCpalette[i][2] = (unsigned char)(colordef.blue >> 8);
57: }
59: /* set the contour colors into the colormap */
60: PetscCall(PetscOptionsGetBool(NULL, NULL, "-draw_fast", &fast, NULL));
61: PetscCall(PetscDrawUtilitySetCmap(NULL, ncolors, R, G, B));
62: for (i = 0, k = PETSC_DRAW_BASIC_COLORS; i < ncolors; i++, k++) {
63: colordef.red = (unsigned short)(R[i] << 8);
64: colordef.green = (unsigned short)(G[i] << 8);
65: colordef.blue = (unsigned short)(B[i] << 8);
66: colordef.flags = DoRed | DoGreen | DoBlue;
67: colordef.pixel = gCmapping[PETSC_DRAW_BLACK];
68: if (!fast) XAllocColor(display, gColormap, &colordef);
69: gCmapping[k] = colordef.pixel;
70: gCpalette[k][0] = R[i];
71: gCpalette[k][1] = G[i];
72: gCpalette[k][2] = B[i];
73: }
75: PetscCall(PetscInfo(NULL, "Successfully allocated colors\n"));
76: PetscFunctionReturn(PETSC_SUCCESS);
77: }
79: /*
80: Keep a record of which pixel numbers in the cmap have been
81: used so far; this is to allow us to try to reuse as much of the current
82: colormap as possible.
83: */
84: static PetscBool cmap_pixvalues_used[PETSC_DRAW_MAXCOLOR];
85: static int cmap_base = 0;
87: static PetscErrorCode PetscDrawSetUpColormap_Private(Display *display, int screen, Visual *visual, Colormap colormap)
88: {
89: int found, i, k, ncolors = PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS;
90: unsigned char R[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
91: unsigned char G[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
92: unsigned char B[PETSC_DRAW_MAXCOLOR - PETSC_DRAW_BASIC_COLORS];
93: Colormap defaultmap = DefaultColormap(display, screen);
94: XColor colordef;
95: PetscBool fast = PETSC_FALSE;
97: PetscFunctionBegin;
98: if (colormap) gColormap = colormap;
99: else gColormap = XCreateColormap(display, RootWindow(display, screen), visual, AllocAll);
101: cmap_base = 0;
103: PetscCall(PetscMemzero(cmap_pixvalues_used, sizeof(cmap_pixvalues_used)));
105: /* set the basic colors into the color map */
106: for (i = 0; i < PETSC_DRAW_BASIC_COLORS; i++) {
107: XParseColor(display, gColormap, colornames[i], &colordef);
108: /* try to allocate the color in the default-map */
109: found = XAllocColor(display, defaultmap, &colordef);
110: /* use it, if it exists and is not already used in the new colormap */
111: if (found && colordef.pixel < PETSC_DRAW_MAXCOLOR && !cmap_pixvalues_used[colordef.pixel]) {
112: cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
113: /* otherwise search for the next available slot */
114: } else {
115: while (cmap_pixvalues_used[cmap_base]) cmap_base++;
116: colordef.pixel = cmap_base;
117: cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
118: }
119: XStoreColor(display, gColormap, &colordef);
120: gCmapping[i] = colordef.pixel;
121: gCpalette[i][0] = (unsigned char)(colordef.red >> 8);
122: gCpalette[i][1] = (unsigned char)(colordef.green >> 8);
123: gCpalette[i][2] = (unsigned char)(colordef.blue >> 8);
124: }
126: /* set the contour colors into the colormap */
127: PetscCall(PetscOptionsGetBool(NULL, NULL, "-draw_fast", &fast, NULL));
128: PetscCall(PetscDrawUtilitySetCmap(NULL, ncolors, R, G, B));
129: for (i = 0, k = PETSC_DRAW_BASIC_COLORS; i < ncolors; i++, k++) {
130: colordef.red = (unsigned short)(R[i] << 8);
131: colordef.green = (unsigned short)(G[i] << 8);
132: colordef.blue = (unsigned short)(B[i] << 8);
133: colordef.flags = DoRed | DoGreen | DoBlue;
134: colordef.pixel = gCmapping[PETSC_DRAW_BLACK];
135: if (!fast) {
136: /* try to allocate the color in the default-map */
137: found = XAllocColor(display, defaultmap, &colordef);
138: /* use it, if it exists and is not already used in the new colormap */
139: if (found && colordef.pixel < PETSC_DRAW_MAXCOLOR && !cmap_pixvalues_used[colordef.pixel]) {
140: cmap_pixvalues_used[colordef.pixel] = PETSC_TRUE;
141: /* otherwise search for the next available slot */
142: } else {
143: while (cmap_pixvalues_used[cmap_base]) cmap_base++;
144: colordef.pixel = cmap_base;
145: cmap_pixvalues_used[cmap_base++] = PETSC_TRUE;
146: }
147: XStoreColor(display, gColormap, &colordef);
148: }
149: gCmapping[k] = colordef.pixel;
150: gCpalette[k][0] = R[i];
151: gCpalette[k][1] = G[i];
152: gCpalette[k][2] = B[i];
153: }
155: PetscCall(PetscInfo(NULL, "Successfully allocated colors\n"));
156: PetscFunctionReturn(PETSC_SUCCESS);
157: }
159: static PetscErrorCode PetscDrawSetUpColormap_X(Display *display, int screen, Visual *visual, Colormap colormap)
160: {
161: PetscBool sharedcolormap = PETSC_FALSE;
162: XVisualInfo vinfo;
164: PetscFunctionBegin;
165: PetscCall(PetscOptionsGetBool(NULL, NULL, "-draw_x_shared_colormap", &sharedcolormap, NULL));
166: /*
167: Need to determine if window supports allocating a private colormap,
168: */
169: 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))
170: sharedcolormap = PETSC_TRUE;
171: /*
172: Generate the X colormap object
173: */
174: if (sharedcolormap) {
175: PetscCall(PetscDrawSetUpColormap_Shared(display, screen, visual, colormap));
176: } else {
177: PetscCall(PetscDrawSetUpColormap_Private(display, screen, visual, colormap));
178: }
179: PetscFunctionReturn(PETSC_SUCCESS);
180: }
182: PETSC_INTERN PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *, Colormap);
184: PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *XiWin, Colormap colormap)
185: {
186: PetscBool fast = PETSC_FALSE;
188: PetscFunctionBegin;
189: PetscCall(PetscOptionsGetBool(NULL, NULL, "-draw_fast", &fast, NULL));
190: PetscCheck(XiWin->depth >= 8, PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "PETSc Graphics require monitors with at least 8 bit color (256 colors)");
191: if (!gColormap) PetscCall(PetscDrawSetUpColormap_X(XiWin->disp, XiWin->screen, XiWin->vis, colormap));
192: XiWin->cmap = gColormap;
193: XiWin->cmapsize = fast ? PETSC_DRAW_BASIC_COLORS : PETSC_DRAW_MAXCOLOR;
194: PetscCall(PetscMemcpy(XiWin->cmapping, gCmapping, sizeof(XiWin->cmapping)));
195: PetscCall(PetscMemcpy(XiWin->cpalette, gCpalette, sizeof(XiWin->cpalette)));
196: XiWin->background = XiWin->cmapping[PETSC_DRAW_WHITE];
197: XiWin->foreground = XiWin->cmapping[PETSC_DRAW_BLACK];
198: PetscFunctionReturn(PETSC_SUCCESS);
199: }
201: PetscErrorCode PetscDrawXiColormap(PetscDraw_X *XiWin)
202: {
203: return PetscDrawSetColormap_X(XiWin, (Colormap)0);
204: }