]> git.saurik.com Git - wxWidgets.git/blob - src/x11/palette.cpp
Applied patch [ 1407318 ] bitmap clipping / transparency mask (X11 port)
[wxWidgets.git] / src / x11 / palette.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/x11/palette.cpp
3 // Purpose: wxPalette
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 17/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 /*
13 * Colour map
14 *
15 * When constructed with the default constructor, we start from
16 * the wxApp::GetMainColormap, allocating additional read-only cells
17 * in Create(). The cells are freed on the next call to Create()
18 * or when the destructor is called.
19 */
20
21 /* Wolfram Gloger <u7y22ab@sunmail.lrz-muenchen.de>
22 I have implemented basic colormap support for the X11 versions of
23 wxWidgets, notably wxPalette::Create(). The way I did it is to
24 allocate additional read-only color cells in the default colormap. In
25 general you will get arbitrary pixel values assigned to these new
26 cells and therefore I added a method wxPalette::TransferBitmap()
27 which maps the pixel values 0..n to the real ones obtained with
28 Create(). This is only implemented for the popular case of 8-bit
29 depth.
30
31 Allocating read-write color cells would involve installing a private
32 X11 colormap for a particular window, and AFAIK this is not
33 recommended; only the window manager should do this... Also, it is
34 not the functionality that wxPalette::Create() aims to provide.
35 */
36
37 #include "wx/palette.h"
38 #include "wx/window.h"
39 #include "wx/app.h"
40 #include "wx/utils.h"
41
42 #ifdef __VMS__
43 #pragma message disable nosimpint
44 #endif
45
46 #ifdef __VMS__
47 #pragma message enable nosimpint
48 #endif
49 #include "wx/x11/private.h"
50
51 IMPLEMENT_DYNAMIC_CLASS(wxPalette, wxGDIObject)
52 IMPLEMENT_DYNAMIC_CLASS(wxXPalette, wxObject)
53
54 /*
55 * Palette
56 *
57 */
58
59 wxXPalette::wxXPalette()
60 {
61 m_cmap = (WXColormap) 0;
62 m_pix_array_n = 0;
63 m_pix_array = (unsigned long*) 0;
64 m_display = (WXDisplay*) 0;
65 m_destroyable = false;
66 }
67
68 wxPaletteRefData::wxPaletteRefData()
69 {
70 }
71
72 wxPaletteRefData::~wxPaletteRefData()
73 {
74 Display *display = (Display*) NULL;
75
76 wxList::compatibility_iterator node, next;
77
78 for (node = m_palettes.GetFirst(); node; node = next) {
79 wxXPalette *c = (wxXPalette *)node->GetData();
80 unsigned long *pix_array = c->m_pix_array;
81 Colormap cmap = (Colormap) c->m_cmap;
82 bool destroyable = c->m_destroyable;
83 int pix_array_n = c->m_pix_array_n;
84 display = (Display*) c->m_display;
85
86 if (pix_array_n > 0)
87 {
88 #if !wxUSE_NANOX
89 // XFreeColors(display, cmap, pix_array, pix_array_n, 0);
90 // Be careful not to free '0' pixels...
91 int i, j;
92 for(i=j=0; i<pix_array_n; i=j) {
93 while(j<pix_array_n && pix_array[j]!=0) j++;
94 if(j > i) XFreeColors(display, cmap, &pix_array[i], j-i, 0);
95 while(j<pix_array_n && pix_array[j]==0) j++;
96 }
97 #endif
98 delete [] pix_array;
99 }
100
101 if (destroyable)
102 XFreeColormap(display, cmap);
103
104 next = node->GetNext();
105 m_palettes.Erase(node);
106 delete c;
107 }
108 }
109
110 wxPalette::wxPalette()
111 {
112 }
113
114 wxPalette::wxPalette(int n, const unsigned char *red, const unsigned char *green, const unsigned char *blue)
115 {
116 Create(n, red, green, blue);
117 }
118
119 wxPalette::~wxPalette()
120 {
121 }
122
123 bool wxPalette::Create(int n, const unsigned char *red, const unsigned char *green, const unsigned char *blue)
124 {
125 UnRef();
126
127 if (!n) {
128 return false;
129 }
130
131 m_refData = new wxPaletteRefData;
132
133 XColor xcol;
134 Display* display = (Display*) wxGetDisplay();
135
136 unsigned long *pix_array;
137 Colormap cmap;
138 int pix_array_n;
139
140 cmap = (Colormap) wxTheApp->GetMainColormap(display);
141
142 pix_array = new unsigned long[n];
143 if (!pix_array)
144 return false;
145
146 pix_array_n = n;
147 xcol.flags = DoRed | DoGreen | DoBlue;
148 for(int i = 0; i < n; i++) {
149 xcol.red = (unsigned short)red[i] << 8;
150 xcol.green = (unsigned short)green[i] << 8;
151 xcol.blue = (unsigned short)blue[i] << 8;
152 pix_array[i] = (XAllocColor(display, cmap, &xcol) == 0) ? 0 : xcol.pixel;
153 }
154
155 wxXPalette *c = new wxXPalette;
156
157 c->m_pix_array_n = pix_array_n;
158 c->m_pix_array = pix_array;
159 c->m_cmap = (WXColormap) cmap;
160 c->m_display = (WXDisplay*) display;
161 c->m_destroyable = false;
162 M_PALETTEDATA->m_palettes.Append(c);
163
164 return true;
165 }
166
167 int wxPalette::GetPixel(unsigned char red, unsigned char green, unsigned char blue) const
168 {
169 if ( !m_refData )
170 return wxNOT_FOUND;
171
172 // TODO
173 return wxNOT_FOUND;
174 }
175
176 bool wxPalette::GetRGB(int index, unsigned char *WXUNUSED(red), unsigned char *WXUNUSED(green), unsigned char *WXUNUSED(blue)) const
177 {
178 if ( !m_refData )
179 return false;
180
181 if (index < 0 || index > 255)
182 return false;
183
184 // TODO
185 return false;
186 }
187
188 WXColormap wxPalette::GetXColormap(WXDisplay* display) const
189 {
190 if (!M_PALETTEDATA || (M_PALETTEDATA->m_palettes.GetCount() == 0))
191 return wxTheApp->GetMainColormap(display);
192
193 wxList::compatibility_iterator node = M_PALETTEDATA->m_palettes.GetFirst();
194 if (!display && node)
195 {
196 wxXPalette* p = (wxXPalette*) node->GetData();
197 return p->m_cmap;
198 }
199 while (node)
200 {
201 wxXPalette* p = (wxXPalette*) node->GetData();
202 if (p->m_display == display)
203 return p->m_cmap;
204
205 node = node->GetNext();
206 }
207
208 /* Make a new one: */
209 wxXPalette *c = new wxXPalette;
210 wxXPalette *first = (wxXPalette *)M_PALETTEDATA->m_palettes.GetFirst()->GetData();
211 XColor xcol;
212 int pix_array_n = first->m_pix_array_n;
213
214 c->m_pix_array_n = pix_array_n;
215 c->m_pix_array = new unsigned long[pix_array_n];
216 c->m_display = display;
217 c->m_cmap = wxTheApp->GetMainColormap(display);
218 c->m_destroyable = false;
219
220 xcol.flags = DoRed | DoGreen | DoBlue;
221 int i;
222 for (i = 0; i < pix_array_n; i++)
223 {
224 xcol.pixel = first->m_pix_array[i];
225 XQueryColor((Display*) first->m_display, (Colormap) first->m_cmap, &xcol);
226 c->m_pix_array[i] =
227 (XAllocColor((Display*) display, (Colormap) c->m_cmap, &xcol) == 0) ? 0 : xcol.pixel;
228 }
229
230 // wxPalette* nonConstThis = (wxPalette*) this;
231
232 M_PALETTEDATA->m_palettes.Append(c);
233
234 return c->m_cmap;
235 }
236
237 bool wxPalette::TransferBitmap(void *data, int depth, int size)
238 {
239 switch(depth) {
240 case 8:
241 {
242 unsigned char *uptr = (unsigned char *)data;
243 int pix_array_n;
244 unsigned long *pix_array = GetXPixArray((Display*) wxGetDisplay(), &pix_array_n);
245 while(size-- > 0)
246 {
247 if((int)*uptr < pix_array_n)
248 *uptr = (unsigned char)pix_array[*uptr];
249 uptr++;
250 }
251
252 return true;
253 }
254 default:
255 return false;
256 }
257 }
258
259 bool wxPalette::TransferBitmap8(unsigned char *data, unsigned long sz,
260 void *dest, unsigned int bpp)
261 {
262 int pix_array_n;
263 unsigned long *pix_array = GetXPixArray((Display*) wxGetDisplay(), &pix_array_n);
264 switch(bpp) {
265 case 8: {
266 unsigned char *dptr = (unsigned char *)dest;
267 while(sz-- > 0) {
268 if((int)*data < pix_array_n)
269 *dptr = (unsigned char)pix_array[*data];
270 data++;
271 dptr++;
272 }
273 break;
274 }
275 case 16: {
276 unsigned short *dptr = (unsigned short *)dest;
277 while(sz-- > 0) {
278 if((int)*data < pix_array_n)
279 *dptr = (unsigned short)pix_array[*data];
280 data++;
281 dptr++;
282 }
283 break;
284 }
285 case 24: {
286 struct rgb24 { unsigned char r, g, b; } *dptr = (struct rgb24 *)dest;
287 while(sz-- > 0) {
288 if((int)*data < pix_array_n) {
289 dptr->r = pix_array[*data] & 0xFF;
290 dptr->g = (pix_array[*data] >> 8) & 0xFF;
291 dptr->b = (pix_array[*data] >> 16) & 0xFF;
292 }
293 data++;
294 dptr++;
295 }
296 break;
297 }
298 case 32: {
299 unsigned long *dptr = (unsigned long *)dest;
300 while(sz-- > 0) {
301 if((int)*data < pix_array_n)
302 *dptr = pix_array[*data];
303 data++;
304 dptr++;
305 }
306 break;
307 }
308 default:
309 return false;
310 }
311 return true;
312 }
313
314 unsigned long *wxPalette::GetXPixArray(WXDisplay *display, int *n)
315 {
316 if (!M_PALETTEDATA)
317 return (unsigned long*) 0;
318 wxList::compatibility_iterator node;
319
320 for (node = M_PALETTEDATA->m_palettes.GetFirst(); node; node = node->GetNext())
321 {
322 wxXPalette *c = (wxXPalette *)node->GetData();
323 if (c->m_display == display)
324 {
325 if (n)
326 *n = c->m_pix_array_n;
327 return c->m_pix_array;
328 }
329 }
330
331 /* Not found; call GetXColormap, which will create it, then this again */
332 if (GetXColormap(display))
333 return GetXPixArray(display, n);
334 else
335 return (unsigned long*) 0;
336 }
337
338 void wxPalette::PutXColormap(WXDisplay* display, WXColormap cm, bool dp)
339 {
340 UnRef();
341
342 m_refData = new wxPaletteRefData;
343
344 wxXPalette *c = new wxXPalette;
345
346 c->m_pix_array_n = 0;
347 c->m_pix_array = (unsigned long*) NULL;
348 c->m_display = display;
349 c->m_cmap = cm;
350 c->m_destroyable = dp;
351
352 M_PALETTEDATA->m_palettes.Append(c);
353 }