1 /*
2 Code for managing color the X implementation of the PetscDraw routines.
3
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.
6
7 */
8 #include <../src/sys/classes/draw/impls/x/ximpl.h>
9 #include <X11/Xatom.h>
10
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"};
14
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
19
20 This is new code written 2/26/1999 Barry Smith,I hope it can replace
21 some older,rather confusing code.
22
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.
27
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.
31
32 */
33 static Colormap gColormap = 0;
34 static PetscDrawXiPixVal gCmapping[PETSC_DRAW_MAXCOLOR];
35 static unsigned char gCpalette[PETSC_DRAW_MAXCOLOR][3];
36
PetscDrawSetUpColormap_Shared(Display * display,int screen,Visual * visual,Colormap colormap)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;
45
46 PetscFunctionBegin;
47 if (colormap) gColormap = colormap;
48 else gColormap = DefaultColormap(display, screen);
49
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 }
58
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 }
74
75 PetscCall(PetscInfo(NULL, "Successfully allocated colors\n"));
76 PetscFunctionReturn(PETSC_SUCCESS);
77 }
78
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;
86
PetscDrawSetUpColormap_Private(Display * display,int screen,Visual * visual,Colormap colormap)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;
96
97 PetscFunctionBegin;
98 if (colormap) gColormap = colormap;
99 else gColormap = XCreateColormap(display, RootWindow(display, screen), visual, AllocAll);
100
101 cmap_base = 0;
102
103 PetscCall(PetscMemzero(cmap_pixvalues_used, sizeof(cmap_pixvalues_used)));
104
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 }
125
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 }
154
155 PetscCall(PetscInfo(NULL, "Successfully allocated colors\n"));
156 PetscFunctionReturn(PETSC_SUCCESS);
157 }
158
PetscDrawSetUpColormap_X(Display * display,int screen,Visual * visual,Colormap colormap)159 static PetscErrorCode PetscDrawSetUpColormap_X(Display *display, int screen, Visual *visual, Colormap colormap)
160 {
161 PetscBool sharedcolormap = PETSC_FALSE;
162 XVisualInfo vinfo;
163
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 }
181
182 PETSC_INTERN PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *, Colormap);
183
PetscDrawSetColormap_X(PetscDraw_X * XiWin,Colormap colormap)184 PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *XiWin, Colormap colormap)
185 {
186 PetscBool fast = PETSC_FALSE;
187
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 }
200
PetscDrawXiColormap(PetscDraw_X * XiWin)201 PetscErrorCode PetscDrawXiColormap(PetscDraw_X *XiWin)
202 {
203 return PetscDrawSetColormap_X(XiWin, (Colormap)0);
204 }
205