]>
Commit | Line | Data |
---|---|---|
4bb6408c JS |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: bitmap.cpp | |
3 | // Purpose: wxBitmap | |
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 | #ifdef __GNUG__ | |
13 | #pragma implementation "bitmap.h" | |
14 | #endif | |
15 | ||
16 | #include "wx/setup.h" | |
17 | #include "wx/utils.h" | |
18 | #include "wx/palette.h" | |
19 | #include "wx/bitmap.h" | |
20 | #include "wx/icon.h" | |
21 | #include "wx/log.h" | |
22 | ||
f97c9854 JS |
23 | #include <Xm/Xm.h> |
24 | ||
25 | #include "wx/motif/private.h" | |
26 | ||
27 | // TODO: correct symbol, path? | |
28 | #if USE_XPM | |
29 | #include <X11/xpm.h> | |
30 | #endif | |
31 | ||
4bb6408c JS |
32 | #if !USE_SHARED_LIBRARIES |
33 | IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject) | |
34 | IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject) | |
35 | #endif | |
36 | ||
37 | wxBitmapRefData::wxBitmapRefData() | |
38 | { | |
39 | m_ok = FALSE; | |
40 | m_width = 0; | |
41 | m_height = 0; | |
42 | m_depth = 0; | |
43 | m_quality = 0; | |
44 | m_numColors = 0; | |
45 | m_bitmapMask = NULL; | |
16c1f7f3 JS |
46 | |
47 | m_pixmap = (WXPixmap) 0; | |
48 | m_display = (WXDisplay*) 0; | |
f97c9854 JS |
49 | |
50 | m_freePixmap = TRUE; //TODO: necessary? | |
51 | m_freeColors = (unsigned long*) 0; | |
52 | m_freeColorsCount = 0; | |
53 | ||
54 | // These 5 variables are for wxControl | |
55 | m_insensPixmap = (WXPixmap) 0; | |
56 | m_labelPixmap = (WXPixmap) 0; | |
57 | m_armPixmap = (WXPixmap) 0; | |
58 | m_image = (WXImage*) 0; | |
59 | m_insensImage = (WXImage*) 0; | |
4bb6408c JS |
60 | } |
61 | ||
62 | wxBitmapRefData::~wxBitmapRefData() | |
63 | { | |
f97c9854 JS |
64 | if (m_labelPixmap) |
65 | XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_labelPixmap); | |
66 | ||
67 | if (m_armPixmap) | |
68 | XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_armPixmap); | |
69 | ||
70 | if (m_insensPixmap) | |
71 | XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_insensPixmap); | |
72 | ||
73 | if (m_image) | |
74 | { | |
75 | XmUninstallImage ((XImage*) m_image); | |
76 | XtFree ((char *) (XImage*) m_image); | |
77 | } | |
78 | ||
79 | if (m_insensImage) | |
80 | { | |
81 | XmUninstallImage ((XImage*) m_insensImage); | |
82 | delete[] ((XImage*) m_insensImage)->data; | |
83 | XtFree ((char *) (XImage*) m_insensImage); | |
84 | } | |
85 | if (m_pixmap && m_freePixmap) | |
86 | XFreePixmap ((Display*) m_display, (Pixmap) m_pixmap); | |
87 | ||
88 | if (m_freeColors) | |
89 | { | |
90 | int screen = DefaultScreen((Display*) m_display); | |
91 | Colormap cmp = DefaultColormap((Display*) m_display,screen); | |
92 | long llp; | |
93 | for(llp = 0;llp < m_freeColorsCount;llp++) | |
94 | XFreeColors((Display*) m_display, cmp, &m_freeColors[llp], 1, 0L); | |
95 | delete m_freeColors; | |
96 | }; | |
4bb6408c JS |
97 | |
98 | if (m_bitmapMask) | |
99 | delete m_bitmapMask; | |
100 | m_bitmapMask = NULL; | |
101 | } | |
102 | ||
103 | wxList wxBitmap::sm_handlers; | |
104 | ||
105 | wxBitmap::wxBitmap() | |
106 | { | |
107 | m_refData = NULL; | |
108 | ||
109 | if ( wxTheBitmapList ) | |
110 | wxTheBitmapList->AddBitmap(this); | |
111 | } | |
112 | ||
113 | wxBitmap::~wxBitmap() | |
114 | { | |
115 | if (wxTheBitmapList) | |
116 | wxTheBitmapList->DeleteObject(this); | |
117 | } | |
118 | ||
f97c9854 | 119 | wxBitmap::wxBitmap(const char bits[], int width, int height, int depth) |
4bb6408c JS |
120 | { |
121 | m_refData = new wxBitmapRefData; | |
122 | ||
f97c9854 | 123 | (void) Create((void*) bits, wxBITMAP_TYPE_XBM_DATA, width, height, depth); |
4bb6408c JS |
124 | |
125 | if ( wxTheBitmapList ) | |
126 | wxTheBitmapList->AddBitmap(this); | |
127 | } | |
128 | ||
129 | wxBitmap::wxBitmap(int w, int h, int d) | |
130 | { | |
131 | (void)Create(w, h, d); | |
132 | ||
133 | if ( wxTheBitmapList ) | |
134 | wxTheBitmapList->AddBitmap(this); | |
135 | } | |
136 | ||
137 | wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth) | |
138 | { | |
139 | (void) Create(data, type, width, height, depth); | |
140 | ||
141 | if ( wxTheBitmapList ) | |
142 | wxTheBitmapList->AddBitmap(this); | |
143 | } | |
144 | ||
145 | wxBitmap::wxBitmap(const wxString& filename, long type) | |
146 | { | |
147 | LoadFile(filename, (int)type); | |
148 | ||
149 | if ( wxTheBitmapList ) | |
150 | wxTheBitmapList->AddBitmap(this); | |
151 | } | |
152 | ||
f97c9854 JS |
153 | // Create from XPM data |
154 | static wxControl* sg_Control = NULL; | |
155 | wxBitmap::wxBitmap(const char **data, wxControl* control) | |
4bb6408c | 156 | { |
f97c9854 JS |
157 | // Pass the control to the Create function using a global |
158 | sg_Control = control; | |
159 | ||
4bb6408c | 160 | (void) Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0); |
f97c9854 JS |
161 | |
162 | sg_Control = (wxControl*) NULL; | |
4bb6408c | 163 | } |
4bb6408c JS |
164 | |
165 | bool wxBitmap::Create(int w, int h, int d) | |
166 | { | |
167 | UnRef(); | |
168 | ||
169 | m_refData = new wxBitmapRefData; | |
170 | ||
f97c9854 JS |
171 | if (d < 1) |
172 | d = wxDisplayDepth(); | |
173 | ||
4bb6408c JS |
174 | M_BITMAPDATA->m_width = w; |
175 | M_BITMAPDATA->m_height = h; | |
176 | M_BITMAPDATA->m_depth = d; | |
f97c9854 | 177 | M_BITMAPDATA->m_freePixmap = TRUE; |
4bb6408c | 178 | |
f97c9854 | 179 | Display *dpy = (Display*) wxGetDisplay(); |
4bb6408c | 180 | |
f97c9854 JS |
181 | M_BITMAPDATA->m_display = dpy; /* MATTHEW: [4] Remember the display */ |
182 | ||
183 | M_BITMAPDATA->m_pixmap = (WXPixmap) XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)), | |
184 | w, h, d); | |
185 | ||
186 | M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_pixmap != (WXPixmap) 0) ; | |
4bb6408c JS |
187 | return M_BITMAPDATA->m_ok; |
188 | } | |
189 | ||
190 | bool wxBitmap::LoadFile(const wxString& filename, long type) | |
191 | { | |
192 | UnRef(); | |
193 | ||
194 | m_refData = new wxBitmapRefData; | |
195 | ||
196 | wxBitmapHandler *handler = FindHandler(type); | |
197 | ||
198 | if ( handler == NULL ) { | |
199 | wxLogWarning("no bitmap handler for type %d defined.", type); | |
200 | ||
201 | return FALSE; | |
202 | } | |
203 | ||
204 | return handler->LoadFile(this, filename, type, -1, -1); | |
205 | } | |
206 | ||
207 | bool wxBitmap::Create(void *data, long type, int width, int height, int depth) | |
208 | { | |
209 | UnRef(); | |
210 | ||
211 | m_refData = new wxBitmapRefData; | |
212 | ||
213 | wxBitmapHandler *handler = FindHandler(type); | |
214 | ||
215 | if ( handler == NULL ) { | |
216 | wxLogWarning("no bitmap handler for type %d defined.", type); | |
217 | ||
218 | return FALSE; | |
219 | } | |
220 | ||
221 | return handler->Create(this, data, type, width, height, depth); | |
222 | } | |
223 | ||
224 | bool wxBitmap::SaveFile(const wxString& filename, int type, const wxPalette *palette) | |
225 | { | |
226 | wxBitmapHandler *handler = FindHandler(type); | |
227 | ||
228 | if ( handler == NULL ) { | |
229 | wxLogWarning("no bitmap handler for type %d defined.", type); | |
230 | ||
231 | return FALSE; | |
232 | } | |
233 | ||
234 | return handler->SaveFile(this, filename, type, palette); | |
235 | } | |
236 | ||
237 | void wxBitmap::SetWidth(int w) | |
238 | { | |
239 | if (!M_BITMAPDATA) | |
240 | m_refData = new wxBitmapRefData; | |
241 | ||
242 | M_BITMAPDATA->m_width = w; | |
243 | } | |
244 | ||
245 | void wxBitmap::SetHeight(int h) | |
246 | { | |
247 | if (!M_BITMAPDATA) | |
248 | m_refData = new wxBitmapRefData; | |
249 | ||
250 | M_BITMAPDATA->m_height = h; | |
251 | } | |
252 | ||
253 | void wxBitmap::SetDepth(int d) | |
254 | { | |
255 | if (!M_BITMAPDATA) | |
256 | m_refData = new wxBitmapRefData; | |
257 | ||
258 | M_BITMAPDATA->m_depth = d; | |
259 | } | |
260 | ||
261 | void wxBitmap::SetQuality(int q) | |
262 | { | |
263 | if (!M_BITMAPDATA) | |
264 | m_refData = new wxBitmapRefData; | |
265 | ||
266 | M_BITMAPDATA->m_quality = q; | |
267 | } | |
268 | ||
269 | void wxBitmap::SetOk(bool isOk) | |
270 | { | |
271 | if (!M_BITMAPDATA) | |
272 | m_refData = new wxBitmapRefData; | |
273 | ||
274 | M_BITMAPDATA->m_ok = isOk; | |
275 | } | |
276 | ||
277 | void wxBitmap::SetPalette(const wxPalette& palette) | |
278 | { | |
279 | if (!M_BITMAPDATA) | |
280 | m_refData = new wxBitmapRefData; | |
281 | ||
282 | M_BITMAPDATA->m_bitmapPalette = palette ; | |
283 | } | |
284 | ||
285 | void wxBitmap::SetMask(wxMask *mask) | |
286 | { | |
287 | if (!M_BITMAPDATA) | |
288 | m_refData = new wxBitmapRefData; | |
289 | ||
290 | M_BITMAPDATA->m_bitmapMask = mask ; | |
291 | } | |
292 | ||
293 | void wxBitmap::AddHandler(wxBitmapHandler *handler) | |
294 | { | |
295 | sm_handlers.Append(handler); | |
296 | } | |
297 | ||
298 | void wxBitmap::InsertHandler(wxBitmapHandler *handler) | |
299 | { | |
300 | sm_handlers.Insert(handler); | |
301 | } | |
302 | ||
303 | bool wxBitmap::RemoveHandler(const wxString& name) | |
304 | { | |
305 | wxBitmapHandler *handler = FindHandler(name); | |
306 | if ( handler ) | |
307 | { | |
308 | sm_handlers.DeleteObject(handler); | |
309 | return TRUE; | |
310 | } | |
311 | else | |
312 | return FALSE; | |
313 | } | |
314 | ||
315 | wxBitmapHandler *wxBitmap::FindHandler(const wxString& name) | |
316 | { | |
317 | wxNode *node = sm_handlers.First(); | |
318 | while ( node ) | |
319 | { | |
320 | wxBitmapHandler *handler = (wxBitmapHandler *)node->Data(); | |
321 | if ( handler->GetName() == name ) | |
322 | return handler; | |
323 | node = node->Next(); | |
324 | } | |
325 | return NULL; | |
326 | } | |
327 | ||
328 | wxBitmapHandler *wxBitmap::FindHandler(const wxString& extension, long bitmapType) | |
329 | { | |
330 | wxNode *node = sm_handlers.First(); | |
331 | while ( node ) | |
332 | { | |
333 | wxBitmapHandler *handler = (wxBitmapHandler *)node->Data(); | |
334 | if ( handler->GetExtension() == extension && | |
335 | (bitmapType == -1 || handler->GetType() == bitmapType) ) | |
336 | return handler; | |
337 | node = node->Next(); | |
338 | } | |
339 | return NULL; | |
340 | } | |
341 | ||
342 | wxBitmapHandler *wxBitmap::FindHandler(long bitmapType) | |
343 | { | |
344 | wxNode *node = sm_handlers.First(); | |
345 | while ( node ) | |
346 | { | |
347 | wxBitmapHandler *handler = (wxBitmapHandler *)node->Data(); | |
348 | if (handler->GetType() == bitmapType) | |
349 | return handler; | |
350 | node = node->Next(); | |
351 | } | |
352 | return NULL; | |
353 | } | |
354 | ||
355 | /* | |
356 | * wxMask | |
357 | */ | |
358 | ||
359 | wxMask::wxMask() | |
360 | { | |
16c1f7f3 | 361 | m_pixmap = (WXPixmap) 0; |
4bb6408c JS |
362 | } |
363 | ||
364 | // Construct a mask from a bitmap and a colour indicating | |
365 | // the transparent area | |
366 | wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour) | |
367 | { | |
16c1f7f3 JS |
368 | m_pixmap = (WXPixmap) 0; |
369 | ||
4bb6408c JS |
370 | Create(bitmap, colour); |
371 | } | |
372 | ||
373 | // Construct a mask from a bitmap and a palette index indicating | |
374 | // the transparent area | |
375 | wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex) | |
376 | { | |
16c1f7f3 | 377 | m_pixmap = (WXPixmap) 0; |
4bb6408c JS |
378 | |
379 | Create(bitmap, paletteIndex); | |
380 | } | |
381 | ||
382 | // Construct a mask from a mono bitmap (copies the bitmap). | |
383 | wxMask::wxMask(const wxBitmap& bitmap) | |
384 | { | |
16c1f7f3 | 385 | m_pixmap = (WXPixmap) 0; |
4bb6408c JS |
386 | |
387 | Create(bitmap); | |
388 | } | |
389 | ||
390 | wxMask::~wxMask() | |
391 | { | |
f97c9854 JS |
392 | // TODO: this may be the wrong display |
393 | if ( m_pixmap ) | |
394 | XFreePixmap ((Display*) wxGetDisplay(), (Pixmap) m_pixmap); | |
4bb6408c JS |
395 | } |
396 | ||
397 | // Create a mask from a mono bitmap (copies the bitmap). | |
398 | bool wxMask::Create(const wxBitmap& bitmap) | |
399 | { | |
400 | // TODO | |
401 | return FALSE; | |
402 | } | |
403 | ||
404 | // Create a mask from a bitmap and a palette index indicating | |
405 | // the transparent area | |
406 | bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex) | |
407 | { | |
408 | // TODO | |
409 | return FALSE; | |
410 | } | |
411 | ||
412 | // Create a mask from a bitmap and a colour indicating | |
413 | // the transparent area | |
414 | bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour) | |
415 | { | |
416 | // TODO | |
417 | return FALSE; | |
418 | } | |
419 | ||
420 | /* | |
421 | * wxBitmapHandler | |
422 | */ | |
423 | ||
424 | IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject) | |
425 | ||
426 | bool wxBitmapHandler::Create(wxBitmap *bitmap, void *data, long type, int width, int height, int depth) | |
427 | { | |
428 | return FALSE; | |
429 | } | |
430 | ||
431 | bool wxBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long type, | |
432 | int desiredWidth, int desiredHeight) | |
433 | { | |
434 | return FALSE; | |
435 | } | |
436 | ||
437 | bool wxBitmapHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette) | |
438 | { | |
439 | return FALSE; | |
440 | } | |
441 | ||
442 | /* | |
443 | * Standard handlers | |
444 | */ | |
445 | ||
f97c9854 | 446 | class WXDLLEXPORT wxXBMFileHandler: public wxBitmapHandler |
4bb6408c | 447 | { |
f97c9854 | 448 | DECLARE_DYNAMIC_CLASS(wxXBMFileHandler) |
4bb6408c | 449 | public: |
f97c9854 | 450 | inline wxXBMFileHandler() |
4bb6408c | 451 | { |
f97c9854 JS |
452 | m_name = "XBM file"; |
453 | m_extension = "xbm"; | |
454 | m_type = wxBITMAP_TYPE_XBM; | |
4bb6408c JS |
455 | }; |
456 | ||
457 | virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags, | |
458 | int desiredWidth, int desiredHeight); | |
459 | }; | |
f97c9854 JS |
460 | IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler, wxBitmapHandler) |
461 | ||
462 | bool wxXBMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags, | |
463 | int desiredWidth, int desiredHeight) | |
464 | { | |
465 | M_BITMAPHANDLERDATA->m_freePixmap = TRUE; | |
466 | ||
467 | int hotX, hotY; | |
468 | unsigned int w, h; | |
469 | Pixmap pixmap; | |
470 | ||
471 | Display *dpy = (Display*) wxGetDisplay(); | |
472 | M_BITMAPDATA->m_display = (WXDisplay*) dpy; | |
473 | ||
474 | int value = XReadBitmapFile (dpy, RootWindow (dpy, DefaultScreen (dpy)), | |
475 | (char*) (const char*) name, &w, &h, &pixmap, &hotX, &hotY); | |
476 | M_BITMAPHANDLERDATA->m_width = w; | |
477 | M_BITMAPHANDLERDATA->m_height = h; | |
478 | M_BITMAPHANDLERDATA->m_depth = 1; | |
479 | M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap; | |
480 | ||
481 | if ((value == BitmapFileInvalid) || | |
482 | (value == BitmapOpenFailed) || | |
483 | (value == BitmapNoMemory)) | |
484 | { | |
485 | M_BITMAPHANDLERDATA->m_ok = FALSE; | |
486 | M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) 0; | |
487 | } | |
488 | else | |
489 | M_BITMAPHANDLERDATA->m_ok = TRUE; | |
490 | ||
491 | return M_BITMAPHANDLERDATA->m_ok ; | |
492 | } | |
493 | ||
494 | class WXDLLEXPORT wxXBMDataHandler: public wxBitmapHandler | |
495 | { | |
496 | DECLARE_DYNAMIC_CLASS(wxXBMDataHandler) | |
497 | public: | |
498 | inline wxXBMDataHandler() | |
499 | { | |
500 | m_name = "XBM data"; | |
501 | m_extension = "xbm"; | |
502 | m_type = wxBITMAP_TYPE_XBM_DATA; | |
503 | }; | |
504 | ||
505 | virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1); | |
506 | }; | |
507 | IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler, wxBitmapHandler) | |
508 | ||
509 | bool wxXBMDataHandler::Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth) | |
510 | { | |
511 | M_BITMAPHANDLERDATA->m_width = width; | |
512 | M_BITMAPHANDLERDATA->m_height = height; | |
513 | M_BITMAPHANDLERDATA->m_depth = 1; | |
514 | M_BITMAPHANDLERDATA->m_freePixmap = TRUE; | |
515 | ||
516 | Display *dpy = (Display*) wxGetDisplay(); | |
517 | M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy; | |
518 | ||
519 | M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) XCreateBitmapFromData (dpy, RootWindow (dpy, DefaultScreen (dpy)), (char*) data, width, height); | |
520 | M_BITMAPHANDLERDATA->m_ok = (M_BITMAPHANDLERDATA->m_pixmap != (WXPixmap) 0) ; | |
521 | ||
522 | // code for wxControl. TODO: can we avoid doing this until we need it? | |
523 | // E.g. have CreateButtonPixmaps which is called on demand. | |
524 | XImage* image = (XImage *) XtMalloc (sizeof (XImage)); | |
525 | image->width = width; | |
526 | image->height = height; | |
527 | image->data = (char*) data; | |
528 | image->depth = 1; | |
529 | image->xoffset = 0; | |
530 | image->format = XYBitmap; | |
531 | image->byte_order = LSBFirst; | |
532 | image->bitmap_unit = 8; | |
533 | image->bitmap_bit_order = LSBFirst; | |
534 | image->bitmap_pad = 8; | |
535 | image->bytes_per_line = (width + 7) >> 3; | |
536 | ||
537 | char tmp[128]; | |
538 | sprintf (tmp, "Im%x", (unsigned int) image); | |
539 | XmInstallImage (image, tmp); | |
540 | ||
541 | // Build our manually stipped pixmap. | |
542 | ||
543 | int bpl = (width + 7) / 8; | |
544 | char *data1 = new char[height * bpl]; | |
545 | char* bits = (char*) data; | |
546 | int i; | |
547 | for (i = 0; i < height; i++) | |
548 | { | |
549 | int mask = i % 2 ? 0x55 : 0xaa; | |
550 | int j; | |
551 | for (j = 0; j < bpl; j++) | |
552 | data1[i * bpl + j] = bits[i * bpl + j] & mask; | |
553 | } | |
554 | XImage* insensImage = (XImage *) XtMalloc (sizeof (XImage)); | |
555 | insensImage->width = width; | |
556 | insensImage->height = height; | |
557 | insensImage->data = data1; | |
558 | insensImage->depth = 1; | |
559 | insensImage->xoffset = 0; | |
560 | insensImage->format = XYBitmap; | |
561 | insensImage->byte_order = LSBFirst; | |
562 | insensImage->bitmap_unit = 8; | |
563 | insensImage->bitmap_bit_order = LSBFirst; | |
564 | insensImage->bitmap_pad = 8; | |
565 | insensImage->bytes_per_line = bpl; | |
566 | ||
567 | sprintf (tmp, "Not%x", (unsigned int)insensImage); | |
568 | XmInstallImage (insensImage, tmp); | |
569 | ||
570 | M_BITMAPHANDLERDATA->m_image = (WXImage*) image; | |
571 | M_BITMAPHANDLERDATA->m_insensImage = (WXImage*) insensImage; | |
572 | ||
573 | return TRUE; | |
574 | } | |
575 | ||
576 | #if USE_XPM | |
577 | class WXDLLEXPORT wxXPMFileHandler: public wxBitmapHandler | |
578 | { | |
579 | DECLARE_DYNAMIC_CLASS(wxXPMFileHandler) | |
580 | public: | |
581 | inline wxXPMFileHandler() | |
582 | { | |
583 | m_name = "XPM file"; | |
584 | m_extension = "xpm"; | |
585 | m_type = wxBITMAP_TYPE_XPM; | |
586 | }; | |
587 | ||
588 | virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags, | |
589 | int desiredWidth, int desiredHeight); | |
590 | virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL); | |
591 | }; | |
592 | ||
593 | IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler) | |
594 | ||
595 | bool wxXPMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags, | |
596 | int desiredWidth, int desiredHeight) | |
597 | { | |
598 | Display *dpy = wxGetDisplay(); | |
599 | M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy; | |
600 | ||
601 | XpmAttributes xpmAttr; | |
602 | Pixmap pixmap; | |
603 | Pixmap mask = 0; | |
604 | ||
605 | M_BITMAPHANDLERDATA->m_ok = FALSE; | |
606 | xpmAttr.valuemask = XpmReturnInfos | XpmCloseness; | |
607 | xpmAttr.closeness = 40000; | |
608 | int errorStatus = XpmReadFileToPixmap(dpy, | |
609 | RootWindow(dpy, DefaultScreen(dpy)), (char*) (const char*) name, | |
610 | &pixmap, &mask, &xpmAttr); | |
611 | ||
612 | if (errorStatus == XpmSuccess) | |
613 | { | |
614 | M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap; | |
615 | if ( mask ) | |
616 | { | |
617 | M_BITMAPHANDLERDATA->m_bitmapMask = new wxMask; | |
618 | M_BITMAPHANDLERDATA->m_bitmapMask->SetPixmap((WXPixmap) mask); | |
619 | } | |
620 | ||
621 | M_BITMAPHANDLERDATA->m_width = xpmAttr.width; | |
622 | M_BITMAPHANDLERDATA->m_height = xpmAttr.height; | |
623 | if ( xpmAttr.npixels > 2 ) | |
624 | { | |
625 | M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ... | |
626 | } else | |
627 | { | |
628 | M_BITMAPHANDLERDATA->m_depth = 1; // mono | |
629 | } | |
630 | ||
631 | M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels; | |
632 | ||
633 | XpmFreeAttributes(&xpmAttr); | |
634 | ||
635 | M_BITMAPHANDLERDATA->m_ok = TRUE; | |
636 | } else | |
637 | { | |
638 | // XpmDebugError(errorStatus, name); | |
639 | M_BITMAPHANDLERDATA->m_ok = FALSE; | |
640 | return FALSE; | |
641 | } | |
642 | } | |
643 | ||
644 | bool wxXPMFileHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette) | |
645 | { | |
646 | if (M_BITMAPHANDLERDATA->m_ok && M_BITMAPHANDLERDATA->m_pixmap) | |
647 | { | |
648 | Display *dpy = (Display*) M_BITMAPHANDLERDATA->m_display; | |
649 | int errorStatus = XpmWriteFileFromPixmap(dpy, (char*) (const char*) name, | |
650 | (Pixmap) M_BITMAPHANDLERDATA->m_pixmap, | |
651 | (M_BITMAPHANDLERDATA->m_bitmapMask ? (Pixmap) M_BITMAPHANDLERDATA->m_bitmapMask->GetPixmap() : (Pixmap) 0), | |
652 | (XpmAttributes *) NULL); | |
653 | if (errorStatus == XpmSuccess) | |
654 | return TRUE; | |
655 | else | |
656 | return FALSE; | |
657 | } | |
658 | else | |
659 | return FALSE; | |
660 | } | |
661 | ||
662 | class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler | |
663 | { | |
664 | DECLARE_DYNAMIC_CLASS(wxXPMDataHandler) | |
665 | public: | |
666 | inline wxXBMDataHandler() | |
667 | { | |
668 | m_name = "XPM data"; | |
669 | m_extension = "xpm"; | |
670 | m_type = wxBITMAP_TYPE_XPM_DATA; | |
671 | }; | |
672 | ||
673 | virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1); | |
674 | }; | |
675 | IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler) | |
676 | ||
677 | bool wxXPMDataHandler::Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth) | |
678 | { | |
679 | M_BITMAPHANDLERDATA->m_width = width; | |
680 | M_BITMAPHANDLERDATA->m_height = height; | |
681 | M_BITMAPHANDLERDATA->m_depth = 1; | |
682 | M_BITMAPHANDLERDATA->m_freePixmap = TRUE; | |
683 | ||
684 | Display *dpy = wxGetDisplay(); | |
685 | M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy; | |
686 | ||
687 | XpmAttributes xpmAttr; | |
688 | ||
689 | xpmAttr.valuemask = XpmReturnInfos; /* nothing yet, but get infos back */ | |
690 | ||
691 | XpmColorSymbol symbolicColors[4]; | |
692 | if (sg_Control && sg_Control->GetMainWidget()) | |
693 | { | |
694 | symbolicColors[0].name = "foreground"; | |
695 | symbolicColors[0].value = NULL; | |
696 | symbolicColors[1].name = "background"; | |
697 | symbolicColors[1].value = NULL; | |
698 | XtVaGetValues((Widget) sg_Control->GetMainWidget(), | |
699 | XmNforeground, &symbolicColors[0].pixel, | |
700 | XmNbackground, &symbolicColors[1].pixel,NULL); | |
701 | xpmAttr.numsymbols = 2; | |
702 | xpmAttr.colorsymbols = symbolicColors; | |
703 | xpmAttr.valuemask |= XpmColorSymbols; // add flag | |
704 | } | |
705 | ||
706 | Pixmap pixmap; | |
707 | Pixmap mask = 0; | |
708 | int ErrorStatus = XpmCreatePixmapFromData(dpy, RootWindow(dpy, DefaultScreen(dpy)), | |
709 | (char**) data, &pixmap, &mask, &xpmAttr); | |
710 | if (ErrorStatus == XpmSuccess) | |
711 | { | |
712 | // Set attributes | |
713 | M_BITMAPHANDLERDATA->m_width = xpmAttr.width; | |
714 | M_BITMAPHANDLERDATA->m_height = xpmAttr.height; | |
715 | if ( xpmAttr.npixels > 2 ) | |
716 | { | |
717 | M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ... | |
718 | } else | |
719 | { | |
720 | M_BITMAPHANDLERDATA->m_depth = 1; // mono | |
721 | } | |
722 | M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels; | |
723 | XpmFreeAttributes(&xpmAttr); | |
724 | M_BITMAPHANDLERDATA->m_ok = TRUE; | |
725 | M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap; | |
726 | if ( mask ) | |
727 | { | |
728 | M_BITMAPHANDLERDATA->m_bitmapMask = new wxMask; | |
729 | M_BITMAPHANDLERDATA->m_bitmapMask->SetPixmap((WXPixmap) mask); | |
730 | } | |
731 | } | |
732 | else | |
733 | { | |
734 | // XpmDebugError(ErrorStatus, NULL); | |
735 | M_BITMAPHANDLERDATA->m_ok = FALSE; | |
736 | } | |
737 | return M_BITMAPHANDLERDATA->m_ok ; | |
738 | } | |
739 | ||
740 | #endif | |
4bb6408c JS |
741 | |
742 | void wxBitmap::CleanUpHandlers() | |
743 | { | |
744 | wxNode *node = sm_handlers.First(); | |
745 | while ( node ) | |
746 | { | |
747 | wxBitmapHandler *handler = (wxBitmapHandler *)node->Data(); | |
748 | wxNode *next = node->Next(); | |
749 | delete handler; | |
750 | delete node; | |
751 | node = next; | |
752 | } | |
753 | } | |
754 | ||
755 | void wxBitmap::InitStandardHandlers() | |
756 | { | |
f97c9854 JS |
757 | // Initialize all standard bitmap or derived class handlers here. |
758 | AddHandler(new wxXBMFileHandler); | |
759 | AddHandler(new wxXBMDataHandler); | |
760 | ||
761 | // XPM is considered standard for Moif, although it can be omitted if absolutely | |
762 | // necessary. | |
763 | #if USE_XPM | |
4bb6408c JS |
764 | AddHandler(new wxXPMFileHandler); |
765 | AddHandler(new wxXPMDataHandler); | |
f97c9854 JS |
766 | #endif |
767 | } | |
768 | ||
769 | WXPixmap wxBitmap::GetLabelPixmap (WXWidget w) | |
770 | { | |
771 | if (M_BITMAPDATA->m_image == (WXPixmap) 0) | |
772 | return M_BITMAPDATA->m_pixmap; | |
773 | ||
774 | Display *dpy = (Display*) M_BITMAPDATA->m_display; | |
775 | ||
776 | #ifdef FOO | |
777 | /* | |
778 | If we do: | |
779 | if (labelPixmap) return labelPixmap; | |
780 | things can be wrong, because colors can have been changed. | |
781 | ||
782 | If we do: | |
783 | if (labelPixmap) | |
784 | XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ; | |
785 | we got BadDrawable if the pixmap is referenced by multiples widgets | |
786 | ||
787 | this is a catch22!! | |
788 | ||
789 | So, before doing thing really clean, I just do nothing; if the pixmap is | |
790 | referenced by many widgets, Motif performs caching functions. | |
791 | And if pixmap is referenced with multiples colors, we just have some | |
792 | memory leaks... I hope we can deal with them... | |
793 | */ | |
794 | // Must be destroyed, because colours can have been changed! | |
795 | if (M_BITMAPDATA->m_labelPixmap) | |
796 | XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_labelPixmap); | |
797 | #endif | |
798 | ||
799 | char tmp[128]; | |
800 | sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image); | |
801 | ||
802 | Pixel fg, bg; | |
803 | Widget widget = (Widget) w; | |
804 | ||
805 | while (XmIsGadget ( widget )) | |
806 | widget = XtParent (widget); | |
807 | XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL); | |
808 | ||
809 | M_BITMAPDATA->m_labelPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg); | |
810 | ||
811 | return M_BITMAPDATA->m_labelPixmap; | |
812 | } | |
813 | ||
814 | WXPixmap wxBitmap::GetArmPixmap (WXWidget w) | |
815 | { | |
816 | if (M_BITMAPDATA->m_image == (WXPixmap) 0) | |
817 | return M_BITMAPDATA->m_pixmap; | |
818 | ||
819 | Display *dpy = (Display*) M_BITMAPDATA->m_display; | |
820 | #ifdef FOO | |
821 | See GetLabelPixmap () comment | |
822 | // Must be destroyed, because colours can have been changed! | |
823 | if (M_BITMAPDATA->m_armPixmap) | |
824 | XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_armPixmap); | |
825 | #endif | |
826 | ||
827 | char tmp[128]; | |
828 | sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image); | |
829 | ||
830 | Pixel fg, bg; | |
831 | Widget widget = (Widget) w; | |
832 | ||
833 | XtVaGetValues (widget, XmNarmColor, &bg, NULL); | |
834 | while (XmIsGadget (widget)) | |
835 | widget = XtParent (widget); | |
836 | XtVaGetValues (widget, XmNforeground, &fg, NULL); | |
837 | ||
838 | M_BITMAPDATA->m_armPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg); | |
839 | ||
840 | return M_BITMAPDATA->m_armPixmap; | |
841 | } | |
842 | ||
843 | WXPixmap wxBitmap::GetInsensPixmap (WXWidget w) | |
844 | { | |
845 | Display *dpy = (Display*) M_BITMAPDATA->m_display; | |
846 | ||
847 | if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0) | |
848 | return M_BITMAPDATA->m_pixmap; | |
849 | ||
850 | #ifdef FOO | |
851 | See GetLabelPixmap () comment | |
852 | // Must be destroyed, because colours can have been changed! | |
853 | if (M_BITMAPDATA->m_insensPixmap) | |
854 | XmDestroyPixmap (DefaultScreenOfDisplay (dpy), (Pixmap) M_BITMAPDATA->m_insensPixmap); | |
855 | #endif | |
856 | ||
857 | char tmp[128]; | |
858 | sprintf (tmp, "Not%x", (unsigned int) M_BITMAPDATA->m_insensImage); | |
859 | ||
860 | Pixel fg, bg; | |
861 | Widget widget = (Widget) w; | |
862 | ||
863 | while (XmIsGadget (widget)) | |
864 | widget = XtParent (widget); | |
865 | XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL); | |
866 | ||
867 | M_BITMAPDATA->m_insensPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg); | |
868 | ||
869 | return M_BITMAPDATA->m_insensPixmap; | |
870 | } | |
871 | ||
872 | // We may need this sometime... | |
873 | ||
874 | /**************************************************************************** | |
875 | ||
876 | NAME | |
877 | XCreateInsensitivePixmap - create a grayed-out copy of a pixmap | |
878 | ||
879 | SYNOPSIS | |
880 | Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap ) | |
881 | ||
882 | DESCRIPTION | |
883 | This function creates a grayed-out copy of the argument pixmap, suitable | |
884 | for use as a XmLabel's XmNlabelInsensitivePixmap resource. | |
885 | ||
886 | RETURN VALUES | |
887 | The return value is the new Pixmap id or zero on error. Errors include | |
888 | a NULL display argument or an invalid Pixmap argument. | |
889 | ||
890 | ERRORS | |
891 | If one of the XLib functions fail, it will produce a X error. The | |
892 | default X error handler prints a diagnostic and calls exit(). | |
893 | ||
894 | SEE ALSO | |
895 | XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3), | |
896 | XFillRectangle(3), exit(2) | |
897 | ||
898 | AUTHOR | |
899 | John R Veregge - john@puente.jpl.nasa.gov | |
900 | Advanced Engineering and Prototyping Group (AEG) | |
901 | Information Systems Technology Section (395) | |
902 | Jet Propulsion Lab - Calif Institute of Technology | |
903 | ||
904 | *****************************************************************************/ | |
905 | ||
906 | Pixmap | |
907 | XCreateInsensitivePixmap( Display *display, Pixmap pixmap ) | |
908 | ||
909 | { | |
910 | static | |
911 | char stipple_data[] = | |
912 | { | |
913 | 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, | |
914 | 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, | |
915 | 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, | |
916 | 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA | |
917 | }; | |
918 | GC gc; | |
919 | Pixmap ipixmap, stipple; | |
920 | unsigned width, height, depth; | |
921 | ||
922 | Window window; /* These return values */ | |
923 | unsigned border; /* from XGetGeometry() */ | |
924 | int x, y; /* are not needed. */ | |
925 | ||
926 | ipixmap = 0; | |
927 | ||
928 | if ( NULL == display || 0 == pixmap ) | |
929 | return ipixmap; | |
930 | ||
931 | if ( 0 == XGetGeometry( display, pixmap, &window, &x, &y, | |
932 | &width, &height, &border, &depth ) | |
933 | ) | |
934 | return ipixmap; /* BadDrawable: probably an invalid pixmap */ | |
935 | ||
936 | /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap. | |
937 | */ | |
938 | stipple = XCreateBitmapFromData( display, pixmap, stipple_data, 16, 16 ); | |
939 | if ( 0 != stipple ) | |
940 | { | |
941 | gc = XCreateGC( display, pixmap, (XtGCMask)0, (XGCValues*)NULL ); | |
942 | if ( NULL != gc ) | |
943 | { | |
944 | /* Create an identical copy of the argument pixmap. | |
945 | */ | |
946 | ipixmap = XCreatePixmap( display, pixmap, width, height, depth ); | |
947 | if ( 0 != ipixmap ) | |
948 | { | |
949 | /* Copy the argument pixmap into the new pixmap. | |
950 | */ | |
951 | XCopyArea( display, pixmap, ipixmap, | |
952 | gc, 0, 0, width, height, 0, 0 ); | |
953 | ||
954 | /* Refill the new pixmap using the stipple algorithm/pixmap. | |
955 | */ | |
956 | XSetStipple( display, gc, stipple ); | |
957 | XSetFillStyle( display, gc, FillStippled ); | |
958 | XFillRectangle( display, ipixmap, gc, 0, 0, width, height ); | |
959 | } | |
960 | XFreeGC( display, gc ); | |
961 | } | |
962 | XFreePixmap( display, stipple ); | |
963 | } | |
964 | return ipixmap; | |
4bb6408c | 965 | } |
f97c9854 | 966 |