PageRenderTime 133ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/ExtLibs/wxWidgets/src/x11/bitmap.cpp

https://bitbucket.org/lennonchan/cafu
C++ | 1622 lines | 1232 code | 317 blank | 73 comment | 176 complexity | 48ddd849825fa88f89379571f9e192c7 MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: src/x11/bitmap.cpp
  3. // Purpose: wxBitmap
  4. // Author: Julian Smart, Robert Roebling
  5. // Modified by:
  6. // Created: 17/09/98
  7. // RCS-ID: $Id$
  8. // Copyright: (c) Julian Smart, Robert Roebling
  9. // Licence: wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11. // for compilers that support precompilation, includes "wx.h".
  12. #include "wx/wxprec.h"
  13. #include "wx/bitmap.h"
  14. #ifndef WX_PRECOMP
  15. #include "wx/log.h"
  16. #include "wx/app.h"
  17. #include "wx/dcmemory.h"
  18. #include "wx/icon.h"
  19. #include "wx/math.h"
  20. #include "wx/image.h"
  21. #endif
  22. #include "wx/x11/private.h"
  23. /* No point in using libXPM for NanoX */
  24. #if wxUSE_NANOX
  25. #undef wxHAVE_LIB_XPM
  26. #define wxHAVE_LIB_XPM 0
  27. // Copy from the drawable to the wxImage
  28. bool wxGetImageFromDrawable(GR_DRAW_ID drawable, int srcX, int srcY, int width, int height, wxImage& image);
  29. #endif
  30. static WXPixmap wxGetSubPixmap( WXDisplay* xdisplay, WXPixmap xpixmap,
  31. int x, int y, int width, int height,
  32. int depth );
  33. #if wxUSE_XPM
  34. #if wxHAVE_LIB_XPM
  35. #include <X11/xpm.h>
  36. #else
  37. #include "wx/xpmdecod.h"
  38. #include "wx/wfstream.h"
  39. #endif
  40. #endif
  41. //-----------------------------------------------------------------------------
  42. // wxMask
  43. //-----------------------------------------------------------------------------
  44. IMPLEMENT_DYNAMIC_CLASS(wxMask,wxObject)
  45. wxMask::wxMask()
  46. {
  47. m_bitmap = NULL;
  48. m_display = NULL;
  49. }
  50. wxMask::wxMask(const wxMask& mask)
  51. {
  52. m_display = mask.m_display;
  53. if ( !mask.m_bitmap )
  54. {
  55. m_bitmap = NULL;
  56. return;
  57. }
  58. m_size = mask.m_size;
  59. // Duplicate the mask bitmap using the existing wxGetSubPixmap() function.
  60. // There are probably/surely better ways to do it.
  61. m_bitmap = wxGetSubPixmap(m_display, mask.m_bitmap,
  62. 0, 0, m_size.x, m_size.y,
  63. 1);
  64. }
  65. wxMask::wxMask( const wxBitmap& bitmap, const wxColour& colour )
  66. {
  67. m_bitmap = NULL;
  68. Create( bitmap, colour );
  69. }
  70. wxMask::wxMask( const wxBitmap& bitmap, int paletteIndex )
  71. {
  72. m_bitmap = NULL;
  73. Create( bitmap, paletteIndex );
  74. }
  75. wxMask::wxMask( const wxBitmap& bitmap )
  76. {
  77. m_bitmap = NULL;
  78. Create( bitmap );
  79. }
  80. wxMask::~wxMask()
  81. {
  82. if (m_bitmap)
  83. XFreePixmap( (Display*) m_display, (Pixmap) m_bitmap );
  84. }
  85. bool wxMask::Create( const wxBitmap& bitmap,
  86. const wxColour& colour )
  87. {
  88. m_size = bitmap.GetSize();
  89. #if !wxUSE_NANOX
  90. if (m_bitmap)
  91. {
  92. XFreePixmap( (Display*) m_display, (Pixmap) m_bitmap );
  93. m_bitmap = NULL;
  94. }
  95. m_display = bitmap.GetDisplay();
  96. wxImage image = bitmap.ConvertToImage();
  97. if (!image.IsOk()) return false;
  98. m_display = bitmap.GetDisplay();
  99. Display *xdisplay = (Display*) m_display;
  100. int xscreen = DefaultScreen( xdisplay );
  101. Window xroot = RootWindow( xdisplay, xscreen );
  102. m_bitmap = (WXPixmap) XCreatePixmap( xdisplay, xroot, image.GetWidth(), image.GetHeight(), 1 );
  103. GC gc = XCreateGC( xdisplay, (Pixmap) m_bitmap, 0, NULL );
  104. XSetForeground( xdisplay, gc, WhitePixel(xdisplay,xscreen) );
  105. XSetFillStyle( xdisplay, gc, FillSolid );
  106. XFillRectangle( xdisplay, (Pixmap) m_bitmap, gc, 0, 0, image.GetWidth(), image.GetHeight() );
  107. unsigned char *data = image.GetData();
  108. int index = 0;
  109. unsigned char red = colour.Red();
  110. unsigned char green = colour.Green();
  111. unsigned char blue = colour.Blue();
  112. int bpp = wxTheApp->GetVisualInfo(m_display)->m_visualDepth;
  113. if (bpp == 15)
  114. {
  115. red &= 0xf8;
  116. green &= 0xf8;
  117. blue &= 0xf8;
  118. } else
  119. if (bpp == 16)
  120. {
  121. red &= 0xf8;
  122. green &= 0xfc;
  123. blue &= 0xf8;
  124. } else
  125. if (bpp == 12)
  126. {
  127. red &= 0xf0;
  128. green &= 0xf0;
  129. blue &= 0xf0;
  130. }
  131. XSetForeground( xdisplay, gc, BlackPixel(xdisplay,xscreen) );
  132. int width = image.GetWidth();
  133. int height = image.GetHeight();
  134. for (int j = 0; j < height; j++)
  135. {
  136. int start_x = -1;
  137. int i;
  138. for (i = 0; i < width; i++)
  139. {
  140. if ((data[index] == red) &&
  141. (data[index+1] == green) &&
  142. (data[index+2] == blue))
  143. {
  144. if (start_x == -1)
  145. start_x = i;
  146. }
  147. else
  148. {
  149. if (start_x != -1)
  150. {
  151. XDrawLine( xdisplay, (Pixmap) m_bitmap, gc, start_x, j, i-1, j );
  152. start_x = -1;
  153. }
  154. }
  155. index += 3;
  156. }
  157. if (start_x != -1)
  158. XDrawLine( xdisplay, (Pixmap) m_bitmap, gc, start_x, j, i, j );
  159. }
  160. XFreeGC( xdisplay, gc );
  161. return true;
  162. #else
  163. return false;
  164. #endif
  165. // wxUSE_NANOX
  166. }
  167. bool wxMask::Create( const wxBitmap& bitmap, int paletteIndex )
  168. {
  169. unsigned char r,g,b;
  170. wxPalette *pal = bitmap.GetPalette();
  171. wxCHECK_MSG( pal, false, wxT("Cannot create mask from bitmap without palette") );
  172. pal->GetRGB(paletteIndex, &r, &g, &b);
  173. return Create(bitmap, wxColour(r, g, b));
  174. }
  175. bool wxMask::Create( const wxBitmap& bitmap )
  176. {
  177. #if !wxUSE_NANOX
  178. if (m_bitmap)
  179. {
  180. XFreePixmap( (Display*) m_display, (Pixmap) m_bitmap );
  181. m_bitmap = NULL;
  182. }
  183. if (!bitmap.IsOk()) return false;
  184. wxCHECK_MSG( bitmap.GetBitmap(), false, wxT("Cannot create mask from colour bitmap") );
  185. m_display = bitmap.GetDisplay();
  186. int xscreen = DefaultScreen( (Display*) m_display );
  187. Window xroot = RootWindow( (Display*) m_display, xscreen );
  188. m_bitmap = (WXPixmap) XCreatePixmap( (Display*) m_display, xroot, bitmap.GetWidth(), bitmap.GetHeight(), 1 );
  189. if (!m_bitmap) return false;
  190. GC gc = XCreateGC( (Display*) m_display, (Pixmap) m_bitmap, 0, NULL );
  191. XCopyPlane( (Display*) m_display, (Pixmap) bitmap.GetBitmap(), (Pixmap) m_bitmap,
  192. gc, 0, 0, bitmap.GetWidth(), bitmap.GetHeight(), 0, 0, 1 );
  193. XFreeGC( (Display*) m_display, gc );
  194. return true;
  195. #else
  196. return false;
  197. #endif
  198. // wxUSE_NANOX
  199. }
  200. //-----------------------------------------------------------------------------
  201. // wxBitmapRefData
  202. //-----------------------------------------------------------------------------
  203. class wxBitmapRefData : public wxGDIRefData
  204. {
  205. public:
  206. wxBitmapRefData();
  207. wxBitmapRefData(const wxBitmapRefData& data);
  208. virtual ~wxBitmapRefData();
  209. // shouldn't be called more than once as it doesn't free the existing data
  210. bool Create(int width, int height, int depth);
  211. virtual bool IsOk() const { return m_pixmap || m_bitmap; }
  212. Pixmap m_pixmap;
  213. Pixmap m_bitmap;
  214. Display *m_display;
  215. wxMask *m_mask;
  216. int m_width;
  217. int m_height;
  218. int m_bpp;
  219. wxPalette *m_palette;
  220. };
  221. wxBitmapRefData::wxBitmapRefData()
  222. {
  223. m_pixmap = 0;
  224. m_bitmap = 0;
  225. m_display = NULL;
  226. m_mask = NULL;
  227. m_width = 0;
  228. m_height = 0;
  229. m_bpp = 0;
  230. m_palette = NULL;
  231. }
  232. wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData& data)
  233. {
  234. m_pixmap = 0;
  235. m_bitmap = 0;
  236. m_display = data.m_display;
  237. m_mask = NULL; // FIXME: should copy
  238. m_palette = NULL; // FIXME: should copy
  239. Create(data.m_width, data.m_height, data.m_bpp);
  240. }
  241. bool wxBitmapRefData::Create(int width, int height, int depth)
  242. {
  243. m_width = width;
  244. m_height = height;
  245. m_bpp = depth;
  246. m_display = wxGlobalDisplay();
  247. wxCHECK_MSG( m_display, false, wxT("No display") );
  248. int xscreen = DefaultScreen(m_display);
  249. int bpp = DefaultDepth(m_display, xscreen);
  250. if ( depth == -1 )
  251. depth = bpp;
  252. wxCHECK_MSG( (depth == bpp) || (depth == 1), false,
  253. wxT("invalid bitmap depth") );
  254. #if wxUSE_NANOX
  255. m_pixmap = (WXPixmap) GrNewPixmap(width, height, NULL);
  256. #else // !wxUSE_NANOX
  257. Window xroot = RootWindow(m_display, xscreen);
  258. *(depth == 1 ? &m_bitmap : &m_pixmap) =
  259. XCreatePixmap(m_display, xroot, width, height, depth);
  260. #endif // wxUSE_NANOX/!wxUSE_NANOX
  261. wxCHECK_MSG( m_pixmap || m_bitmap, false, wxT("Bitmap creation failed") );
  262. return true;
  263. }
  264. wxBitmapRefData::~wxBitmapRefData()
  265. {
  266. if (m_pixmap)
  267. XFreePixmap(m_display, m_pixmap);
  268. if (m_bitmap)
  269. XFreePixmap(m_display, m_bitmap);
  270. delete m_mask;
  271. delete m_palette;
  272. }
  273. //-----------------------------------------------------------------------------
  274. // helper function
  275. static WXPixmap wxGetSubPixmap( WXDisplay* xdisplay, WXPixmap xpixmap,
  276. int x, int y, int width, int height,
  277. int depth )
  278. {
  279. Display * const dpy = (Display *)xdisplay;
  280. int xscreen = DefaultScreen( dpy );
  281. Window xroot = RootWindow( dpy, xscreen );
  282. Visual* xvisual = DefaultVisual( dpy, xscreen );
  283. XImage* ximage = XCreateImage( dpy, xvisual, depth,
  284. ZPixmap, 0, 0, width, height, 32, 0 );
  285. ximage->data = (char*)malloc( ximage->bytes_per_line * ximage->height );
  286. ximage = XGetSubImage( dpy, (Pixmap)xpixmap,
  287. x, y, width, height,
  288. AllPlanes, ZPixmap, ximage, 0, 0 );
  289. GC gc = XCreateGC( dpy, (Pixmap)xpixmap, 0, NULL );
  290. Pixmap ret = XCreatePixmap( dpy, xroot,
  291. width, height, depth );
  292. XPutImage( dpy, ret, gc, ximage,
  293. 0, 0, 0, 0, width, height );
  294. XDestroyImage( ximage );
  295. XFreeGC( dpy, gc );
  296. return (WXPixmap)ret;
  297. }
  298. //-----------------------------------------------------------------------------
  299. // wxBitmap
  300. //-----------------------------------------------------------------------------
  301. #define M_BMPDATA ((wxBitmapRefData *)m_refData)
  302. IMPLEMENT_DYNAMIC_CLASS(wxBitmap,wxGDIObject)
  303. bool wxBitmap::Create( int width, int height, int depth )
  304. {
  305. UnRef();
  306. wxCHECK_MSG( (width > 0) && (height > 0), false, wxT("invalid bitmap size") );
  307. m_refData = new wxBitmapRefData();
  308. return M_BMPDATA->Create(width, height, depth);
  309. }
  310. bool wxBitmap::Create(const void* data, wxBitmapType type,
  311. int width, int height, int depth)
  312. {
  313. UnRef();
  314. wxBitmapHandler *handler = FindHandler(type);
  315. if ( handler == NULL ) {
  316. wxLogWarning(wxT("no data bitmap handler for type %ld defined."),
  317. (long)type);
  318. return false;
  319. }
  320. return handler->Create(this, data, type, width, height, depth);
  321. }
  322. bool wxBitmap::Create(WXPixmap pixmap)
  323. {
  324. UnRef();
  325. Pixmap xpixmap = (Pixmap)pixmap;
  326. Display* xdisplay = wxGlobalDisplay();
  327. int xscreen = DefaultScreen( xdisplay );
  328. Window xroot = RootWindow( xdisplay, xscreen );
  329. // make a copy of the Pixmap
  330. Window root;
  331. int x, y;
  332. unsigned width, height, border, depth;
  333. XGetGeometry( xdisplay, (Drawable)xpixmap, &root, &x, &y,
  334. &width, &height, &border, &depth );
  335. Pixmap copy = XCreatePixmap( xdisplay, xroot, width, height, depth );
  336. GC gc = XCreateGC( xdisplay, copy, 0, NULL );
  337. XCopyArea( xdisplay, xpixmap, copy, gc, 0, 0, width, height, 0, 0 );
  338. XFreeGC( xdisplay, gc );
  339. // fill in ref data
  340. wxBitmapRefData* ref = new wxBitmapRefData();
  341. if( depth == 1 )
  342. ref->m_bitmap = copy;
  343. else
  344. ref->m_pixmap = copy;
  345. ref->m_display = xdisplay;
  346. ref->m_width = width;
  347. ref->m_height = height;
  348. ref->m_bpp = depth;
  349. m_refData = ref;
  350. return true;
  351. }
  352. wxBitmap::wxBitmap(const char* const* bits)
  353. {
  354. Create(bits, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
  355. }
  356. wxGDIRefData *wxBitmap::CreateGDIRefData() const
  357. {
  358. return new wxBitmapRefData;
  359. }
  360. wxGDIRefData *wxBitmap::CloneGDIRefData(const wxGDIRefData *data) const
  361. {
  362. return new wxBitmapRefData(*static_cast<const wxBitmapRefData *>(data));
  363. }
  364. bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
  365. {
  366. #if wxUSE_NANOX
  367. if (!image.IsOk())
  368. {
  369. wxASSERT_MSG(image.IsOk(), wxT("Invalid wxImage passed to wxBitmap::CreateFromImage."));
  370. return false;
  371. }
  372. int w = image.GetWidth();
  373. int h = image.GetHeight();
  374. if (!Create(w, h, depth))
  375. return false;
  376. // Unfortunately the mask has to be screen-depth since
  377. // 1-bpp bitmaps don't seem to be supported
  378. // TODO: implement transparent drawing, presumably
  379. // by doing several blits as per the Windows
  380. // implementation because Nano-X doesn't support
  381. // XSetClipMask.
  382. // TODO: could perhaps speed this function up
  383. // by making a buffer of pixel values,
  384. // and then calling GrArea to write that to the
  385. // pixmap. See demos/nxroach.c.
  386. bool hasMask = image.HasMask();
  387. GC pixmapGC = GrNewGC();
  388. Pixmap pixmap = (Pixmap) GetPixmap();
  389. GC maskGC = 0;
  390. Pixmap maskPixmap = 0;
  391. unsigned char maskR = 0;
  392. unsigned char maskG = 0;
  393. unsigned char maskB = 0;
  394. if (hasMask)
  395. {
  396. maskR = image.GetMaskRed();
  397. maskG = image.GetMaskGreen();
  398. maskB = image.GetMaskBlue();
  399. maskGC = GrNewGC();
  400. maskPixmap = GrNewPixmap(w, h, 0);
  401. if (!maskPixmap)
  402. hasMask = false;
  403. else
  404. {
  405. wxMask* mask = new wxMask;
  406. mask->SetBitmap((WXPixmap) maskPixmap);
  407. SetMask(mask);
  408. }
  409. }
  410. GR_COLOR lastPixmapColour = 0;
  411. GR_COLOR lastMaskColour = 0;
  412. int i, j;
  413. for (i = 0; i < w; i++)
  414. {
  415. for (j = 0; j < h; j++)
  416. {
  417. unsigned char red = image.GetRed(i, j);
  418. unsigned char green = image.GetGreen(i, j);
  419. unsigned char blue = image.GetBlue(i, j);
  420. GR_COLOR colour = GR_RGB(red, green, blue);
  421. // Efficiency measure
  422. if (colour != lastPixmapColour || (i == 0 && j == 0))
  423. {
  424. GrSetGCForeground(pixmapGC, colour);
  425. lastPixmapColour = colour;
  426. }
  427. GrPoint(pixmap, pixmapGC, i, j);
  428. if (hasMask)
  429. {
  430. // scan the bitmap for the transparent colour and set the corresponding
  431. // pixels in the mask to BLACK and the rest to WHITE
  432. if (maskR == red && maskG == green && maskB == blue)
  433. {
  434. colour = GR_RGB(0, 0, 0);
  435. }
  436. else
  437. {
  438. colour = GR_RGB(255, 255, 255);
  439. }
  440. if (colour != lastMaskColour || (i == 0 && j == 0))
  441. {
  442. GrSetGCForeground(maskGC, colour);
  443. lastMaskColour = colour;
  444. }
  445. GrPoint(maskPixmap, maskGC, i, j);
  446. }
  447. }
  448. }
  449. GrDestroyGC(pixmapGC);
  450. if (hasMask)
  451. GrDestroyGC(maskGC);
  452. return true;
  453. #else
  454. // !wxUSE_NANOX
  455. UnRef();
  456. wxCHECK_MSG( image.IsOk(), false, wxT("invalid image") );
  457. wxCHECK_MSG( depth == -1, false, wxT("invalid bitmap depth") );
  458. m_refData = new wxBitmapRefData();
  459. M_BMPDATA->m_display = wxGlobalDisplay();
  460. Display *xdisplay = (Display*) M_BMPDATA->m_display;
  461. int xscreen = DefaultScreen( xdisplay );
  462. Window xroot = RootWindow( xdisplay, xscreen );
  463. Visual* xvisual = DefaultVisual( xdisplay, xscreen );
  464. int bpp = wxTheApp->GetVisualInfo(M_BMPDATA->m_display)->m_visualDepth;
  465. int width = image.GetWidth();
  466. int height = image.GetHeight();
  467. M_BMPDATA->m_width = width;
  468. M_BMPDATA->m_height = height;
  469. if (depth != 1) depth = bpp;
  470. M_BMPDATA->m_bpp = depth;
  471. if (depth == 1)
  472. {
  473. wxFAIL_MSG( wxT("mono images later") );
  474. }
  475. else
  476. {
  477. // Create image
  478. XImage *data_image = XCreateImage( xdisplay, xvisual, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
  479. data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
  480. if (data_image->data == NULL)
  481. {
  482. wxLogError( wxT("Out of memory.") ); // TODO clean
  483. return false;
  484. }
  485. M_BMPDATA->m_pixmap = XCreatePixmap( xdisplay, xroot, width, height, depth );
  486. // Create mask if necessary
  487. const bool hasMask = image.HasMask();
  488. XImage *mask_image = NULL;
  489. if ( hasMask )
  490. {
  491. mask_image = XCreateImage( xdisplay, xvisual, 1, ZPixmap, 0, 0, width, height, 32, 0 );
  492. mask_image->data = (char*) malloc( mask_image->bytes_per_line * mask_image->height );
  493. if (mask_image->data == NULL)
  494. {
  495. wxLogError( wxT("Out of memory.") ); // TODO clean
  496. return false;
  497. }
  498. wxMask *mask = new wxMask();
  499. mask->SetDisplay( xdisplay );
  500. mask->SetBitmap( (WXPixmap) XCreatePixmap( xdisplay, xroot, width, height, 1 ) );
  501. SetMask( mask );
  502. }
  503. if (bpp < 8) bpp = 8;
  504. // Render
  505. enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
  506. byte_order b_o = RGB;
  507. wxXVisualInfo* vi = wxTheApp->GetVisualInfo(M_BMPDATA->m_display);
  508. unsigned long greenMask = vi->m_visualGreenMask,
  509. redMask = vi->m_visualRedMask,
  510. blueMask = vi->m_visualBlueMask;
  511. if (bpp > 8)
  512. {
  513. if ((redMask > greenMask) && (greenMask > blueMask)) b_o = RGB;
  514. else if ((redMask > blueMask) && (blueMask > greenMask)) b_o = RBG;
  515. else if ((blueMask > redMask) && (redMask > greenMask)) b_o = BRG;
  516. else if ((blueMask > greenMask) && (greenMask > redMask))b_o = BGR;
  517. else if ((greenMask > redMask) && (redMask > blueMask)) b_o = GRB;
  518. else if ((greenMask > blueMask) && (blueMask > redMask)) b_o = GBR;
  519. }
  520. int r_mask = image.GetMaskRed();
  521. int g_mask = image.GetMaskGreen();
  522. int b_mask = image.GetMaskBlue();
  523. unsigned char* data = image.GetData();
  524. wxASSERT_MSG( data, wxT("No image data") );
  525. unsigned char *colorCube =
  526. wxTheApp->GetVisualInfo(M_BMPDATA->m_display)->m_colorCube;
  527. int index = 0;
  528. for (int y = 0; y < height; y++)
  529. {
  530. for (int x = 0; x < width; x++)
  531. {
  532. int r = data[index];
  533. index++;
  534. int g = data[index];
  535. index++;
  536. int b = data[index];
  537. index++;
  538. if (hasMask)
  539. {
  540. if ((r == r_mask) && (b == b_mask) && (g == g_mask))
  541. XPutPixel( mask_image, x, y, 0 );
  542. else
  543. XPutPixel( mask_image, x, y, 1 );
  544. }
  545. switch (bpp)
  546. {
  547. case 8:
  548. {
  549. int pixel = 0;
  550. pixel = colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
  551. XPutPixel( data_image, x, y, pixel );
  552. break;
  553. }
  554. case 12: // SGI only
  555. {
  556. int pixel = 0;
  557. switch (b_o)
  558. {
  559. case RGB: pixel = ((r & 0xf0) << 4) | (g & 0xf0) | ((b & 0xf0) >> 4); break;
  560. case RBG: pixel = ((r & 0xf0) << 4) | (b & 0xf0) | ((g & 0xf0) >> 4); break;
  561. case GRB: pixel = ((g & 0xf0) << 4) | (r & 0xf0) | ((b & 0xf0) >> 4); break;
  562. case GBR: pixel = ((g & 0xf0) << 4) | (b & 0xf0) | ((r & 0xf0) >> 4); break;
  563. case BRG: pixel = ((b & 0xf0) << 4) | (r & 0xf0) | ((g & 0xf0) >> 4); break;
  564. case BGR: pixel = ((b & 0xf0) << 4) | (g & 0xf0) | ((r & 0xf0) >> 4); break;
  565. }
  566. XPutPixel( data_image, x, y, pixel );
  567. break;
  568. }
  569. case 15:
  570. {
  571. int pixel = 0;
  572. switch (b_o)
  573. {
  574. case RGB: pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3); break;
  575. case RBG: pixel = ((r & 0xf8) << 7) | ((b & 0xf8) << 2) | ((g & 0xf8) >> 3); break;
  576. case GRB: pixel = ((g & 0xf8) << 7) | ((r & 0xf8) << 2) | ((b & 0xf8) >> 3); break;
  577. case GBR: pixel = ((g & 0xf8) << 7) | ((b & 0xf8) << 2) | ((r & 0xf8) >> 3); break;
  578. case BRG: pixel = ((b & 0xf8) << 7) | ((r & 0xf8) << 2) | ((g & 0xf8) >> 3); break;
  579. case BGR: pixel = ((b & 0xf8) << 7) | ((g & 0xf8) << 2) | ((r & 0xf8) >> 3); break;
  580. }
  581. XPutPixel( data_image, x, y, pixel );
  582. break;
  583. }
  584. case 16:
  585. {
  586. // I actually don't know if for 16-bit displays, it is alway the green
  587. // component or the second component which has 6 bits.
  588. int pixel = 0;
  589. switch (b_o)
  590. {
  591. case RGB: pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3); break;
  592. case RBG: pixel = ((r & 0xf8) << 8) | ((b & 0xfc) << 3) | ((g & 0xf8) >> 3); break;
  593. case GRB: pixel = ((g & 0xf8) << 8) | ((r & 0xfc) << 3) | ((b & 0xf8) >> 3); break;
  594. case GBR: pixel = ((g & 0xf8) << 8) | ((b & 0xfc) << 3) | ((r & 0xf8) >> 3); break;
  595. case BRG: pixel = ((b & 0xf8) << 8) | ((r & 0xfc) << 3) | ((g & 0xf8) >> 3); break;
  596. case BGR: pixel = ((b & 0xf8) << 8) | ((g & 0xfc) << 3) | ((r & 0xf8) >> 3); break;
  597. }
  598. XPutPixel( data_image, x, y, pixel );
  599. break;
  600. }
  601. case 32:
  602. case 24:
  603. {
  604. int pixel = 0;
  605. switch (b_o)
  606. {
  607. case RGB: pixel = (r << 16) | (g << 8) | b; break;
  608. case RBG: pixel = (r << 16) | (b << 8) | g; break;
  609. case BRG: pixel = (b << 16) | (r << 8) | g; break;
  610. case BGR: pixel = (b << 16) | (g << 8) | r; break;
  611. case GRB: pixel = (g << 16) | (r << 8) | b; break;
  612. case GBR: pixel = (g << 16) | (b << 8) | r; break;
  613. }
  614. XPutPixel( data_image, x, y, pixel );
  615. }
  616. default: break;
  617. }
  618. } // for
  619. } // for
  620. // Blit picture
  621. GC gc = XCreateGC( xdisplay, (Pixmap) M_BMPDATA->m_pixmap, 0, NULL );
  622. XPutImage( xdisplay, (Pixmap) M_BMPDATA->m_pixmap, gc, data_image, 0, 0, 0, 0, width, height );
  623. XDestroyImage( data_image );
  624. XFreeGC( xdisplay, gc );
  625. // Blit mask
  626. if (image.HasMask())
  627. {
  628. GC gc = XCreateGC( xdisplay, (Pixmap) GetMask()->GetBitmap(), 0, NULL );
  629. XPutImage( xdisplay, (Pixmap) GetMask()->GetBitmap(), gc, mask_image, 0, 0, 0, 0, width, height );
  630. XDestroyImage( mask_image );
  631. XFreeGC( xdisplay, gc );
  632. }
  633. }
  634. return true;
  635. #endif
  636. // wxUSE_NANOX
  637. }
  638. wxImage wxBitmap::ConvertToImage() const
  639. {
  640. wxImage image;
  641. wxCHECK_MSG( IsOk(), wxNullImage, wxT("invalid bitmap") );
  642. Display *xdisplay = (Display*) M_BMPDATA->m_display;
  643. wxASSERT_MSG( xdisplay, wxT("No display") );
  644. #if wxUSE_NANOX
  645. //int bpp = DefaultDepth(xdisplay, xscreen);
  646. wxGetImageFromDrawable((Pixmap) GetPixmap(), 0, 0, GetWidth(), GetHeight(), image);
  647. return image;
  648. #else
  649. // !wxUSE_NANOX
  650. int bpp = wxTheApp->GetVisualInfo(M_BMPDATA->m_display)->m_visualDepth;
  651. XImage *x_image = NULL;
  652. if (GetPixmap())
  653. {
  654. x_image = XGetImage( xdisplay, (Pixmap) GetPixmap(),
  655. 0, 0,
  656. GetWidth(), GetHeight(),
  657. AllPlanes, ZPixmap );
  658. } else
  659. if (GetBitmap())
  660. {
  661. x_image = XGetImage( xdisplay, (Pixmap) GetBitmap(),
  662. 0, 0,
  663. GetWidth(), GetHeight(),
  664. AllPlanes, ZPixmap );
  665. } else
  666. {
  667. wxFAIL_MSG( wxT("Ill-formed bitmap") );
  668. }
  669. wxCHECK_MSG( x_image, wxNullImage, wxT("couldn't create image") );
  670. image.Create( GetWidth(), GetHeight() );
  671. char unsigned *data = image.GetData();
  672. if (!data)
  673. {
  674. XDestroyImage( x_image );
  675. wxFAIL_MSG( wxT("couldn't create image") );
  676. return wxNullImage;
  677. }
  678. XImage *x_image_mask = NULL;
  679. if (GetMask())
  680. {
  681. x_image_mask = XGetImage( xdisplay, (Pixmap) GetMask()->GetBitmap(),
  682. 0, 0,
  683. GetWidth(), GetHeight(),
  684. AllPlanes, ZPixmap );
  685. image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
  686. }
  687. int red_shift_right = 0;
  688. int green_shift_right = 0;
  689. int blue_shift_right = 0;
  690. int red_shift_left = 0;
  691. int green_shift_left = 0;
  692. int blue_shift_left = 0;
  693. bool use_shift = false;
  694. if (GetPixmap())
  695. {
  696. wxXVisualInfo* vi = wxTheApp->GetVisualInfo(M_BMPDATA->m_display);
  697. red_shift_right = vi->m_visualRedShift;
  698. red_shift_left = 8 - vi->m_visualRedPrec;
  699. green_shift_right = vi->m_visualGreenShift;
  700. green_shift_left = 8 - vi->m_visualGreenPrec;
  701. blue_shift_right = vi->m_visualBlueShift;
  702. blue_shift_left = 8 - vi->m_visualBluePrec;
  703. use_shift = (vi->m_visualType == GrayScale) ||
  704. (vi->m_visualType != PseudoColor);
  705. }
  706. if (GetBitmap())
  707. {
  708. bpp = 1;
  709. }
  710. XColor *colors = (XColor*)wxTheApp->
  711. GetVisualInfo(M_BMPDATA->m_display)->m_visualColormap;
  712. int width = GetWidth();
  713. int height = GetHeight();
  714. long pos = 0;
  715. for (int j = 0; j < height; j++)
  716. {
  717. for (int i = 0; i < width; i++)
  718. {
  719. unsigned long pixel = XGetPixel( x_image, i, j );
  720. if (bpp == 1)
  721. {
  722. if (pixel == 0)
  723. {
  724. data[pos] = 0;
  725. data[pos+1] = 0;
  726. data[pos+2] = 0;
  727. }
  728. else
  729. {
  730. data[pos] = 255;
  731. data[pos+1] = 255;
  732. data[pos+2] = 255;
  733. }
  734. }
  735. else if (use_shift)
  736. {
  737. data[pos] = (unsigned char)((pixel >> red_shift_right) << red_shift_left);
  738. data[pos+1] = (unsigned char)((pixel >> green_shift_right) << green_shift_left);
  739. data[pos+2] = (unsigned char)((pixel >> blue_shift_right) << blue_shift_left);
  740. }
  741. else if (colors)
  742. {
  743. data[pos] = (unsigned char)(colors[pixel].red >> 8);
  744. data[pos+1] = (unsigned char)(colors[pixel].green >> 8);
  745. data[pos+2] = (unsigned char)(colors[pixel].blue >> 8);
  746. }
  747. else
  748. {
  749. wxFAIL_MSG( wxT("Image conversion failed. Unknown visual type.") );
  750. }
  751. if (x_image_mask)
  752. {
  753. int mask_pixel = XGetPixel( x_image_mask, i, j );
  754. if (mask_pixel == 0)
  755. {
  756. data[pos] = 16;
  757. data[pos+1] = 16;
  758. data[pos+2] = 16;
  759. }
  760. }
  761. pos += 3;
  762. }
  763. }
  764. XDestroyImage( x_image );
  765. if (x_image_mask) XDestroyImage( x_image_mask );
  766. return image;
  767. #endif
  768. // wxUSE_NANOX
  769. }
  770. wxBitmap::wxBitmap( const wxString &filename, wxBitmapType type )
  771. {
  772. LoadFile( filename, type );
  773. }
  774. wxBitmap::wxBitmap( const char bits[], int width, int height, int depth )
  775. {
  776. m_refData = new wxBitmapRefData;
  777. (void) Create(bits, wxBITMAP_TYPE_XBM_DATA, width, height, depth);
  778. }
  779. wxBitmap::~wxBitmap()
  780. {
  781. }
  782. int wxBitmap::GetHeight() const
  783. {
  784. wxCHECK_MSG( IsOk(), -1, wxT("invalid bitmap") );
  785. return M_BMPDATA->m_height;
  786. }
  787. int wxBitmap::GetWidth() const
  788. {
  789. wxCHECK_MSG( IsOk(), -1, wxT("invalid bitmap") );
  790. return M_BMPDATA->m_width;
  791. }
  792. int wxBitmap::GetDepth() const
  793. {
  794. wxCHECK_MSG( IsOk(), -1, wxT("invalid bitmap") );
  795. return M_BMPDATA->m_bpp;
  796. }
  797. wxMask *wxBitmap::GetMask() const
  798. {
  799. wxCHECK_MSG( IsOk(), NULL, wxT("invalid bitmap") );
  800. return M_BMPDATA->m_mask;
  801. }
  802. void wxBitmap::SetMask( wxMask *mask )
  803. {
  804. wxCHECK_RET( IsOk(), wxT("invalid bitmap") );
  805. AllocExclusive();
  806. if (M_BMPDATA->m_mask) delete M_BMPDATA->m_mask;
  807. M_BMPDATA->m_mask = mask;
  808. }
  809. bool wxBitmap::CopyFromIcon(const wxIcon& icon)
  810. {
  811. *this = icon;
  812. return true;
  813. }
  814. wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
  815. {
  816. wxCHECK_MSG( IsOk() &&
  817. (rect.x >= 0) && (rect.y >= 0) &&
  818. (rect.x+rect.width <= M_BMPDATA->m_width ) &&
  819. (rect.y+rect.height <= M_BMPDATA->m_height),
  820. wxNullBitmap, wxT("invalid bitmap or bitmap region") );
  821. wxBitmap ret( rect.width, rect.height, M_BMPDATA->m_bpp );
  822. wxASSERT_MSG( ret.IsOk(), wxT("GetSubBitmap error") );
  823. if( GetMask() )
  824. {
  825. wxMask* mask = new wxMask();
  826. mask->SetDisplay( GetMask()->GetDisplay() );
  827. mask->SetBitmap( wxGetSubPixmap( GetMask()->GetDisplay(),
  828. GetMask()->GetBitmap(),
  829. rect.x, rect.y,
  830. rect.width, rect.height,
  831. 1 ) );
  832. ret.SetMask( mask );
  833. }
  834. if( GetPixmap() )
  835. {
  836. ret.SetPixmap( wxGetSubPixmap( GetDisplay(),
  837. GetPixmap(),
  838. rect.x, rect.y,
  839. rect.width, rect.height,
  840. M_BMPDATA->m_bpp ) );
  841. }
  842. if( GetBitmap() )
  843. {
  844. ret.SetBitmap( wxGetSubPixmap( GetDisplay(),
  845. GetBitmap(),
  846. rect.x, rect.y,
  847. rect.width, rect.height,
  848. 1 ) );
  849. }
  850. return ret;
  851. }
  852. bool wxBitmap::SaveFile( const wxString &name, wxBitmapType type,
  853. const wxPalette *palette ) const
  854. {
  855. wxCHECK_MSG( IsOk(), false, wxT("invalid bitmap") );
  856. wxBitmapHandler *handler = FindHandler(type);
  857. // Try to save the bitmap via wxImage handlers:
  858. if (handler == NULL)
  859. {
  860. wxImage image(this->ConvertToImage());
  861. if (image.IsOk()) return image.SaveFile( name, type );
  862. return false;
  863. }
  864. return handler->SaveFile(this, name, type, palette);
  865. }
  866. bool wxBitmap::LoadFile( const wxString &name, wxBitmapType type )
  867. {
  868. UnRef();
  869. if (!wxFileExists(name)) return false;
  870. wxBitmapHandler *handler = FindHandler(type);
  871. if (handler == NULL)
  872. {
  873. wxImage image;
  874. if (!image.LoadFile( name, type ))
  875. return false;
  876. if (image.IsOk())
  877. {
  878. *this = wxBitmap(image);
  879. return true;
  880. }
  881. else return false;
  882. }
  883. return handler->LoadFile(this, name, type, -1, -1);
  884. }
  885. void wxBitmap::SetPalette(const wxPalette& palette)
  886. {
  887. wxCHECK_RET(IsOk(), wxT("invalid bitmap"));
  888. wxCHECK_RET(GetDepth() > 1 && GetDepth() <= 8,
  889. wxT("cannot set palette for bitmap of this depth"));
  890. AllocExclusive();
  891. wxDELETE(M_BMPDATA->m_palette);
  892. if (!palette.IsOk()) return;
  893. M_BMPDATA->m_palette = new wxPalette(palette);
  894. }
  895. wxPalette *wxBitmap::GetPalette() const
  896. {
  897. if (!IsOk()) return NULL;
  898. return M_BMPDATA->m_palette;
  899. }
  900. void wxBitmap::SetHeight( int height )
  901. {
  902. AllocExclusive();
  903. M_BMPDATA->m_height = height;
  904. }
  905. void wxBitmap::SetWidth( int width )
  906. {
  907. AllocExclusive();
  908. M_BMPDATA->m_width = width;
  909. }
  910. void wxBitmap::SetDepth( int depth )
  911. {
  912. AllocExclusive();
  913. M_BMPDATA->m_bpp = depth;
  914. }
  915. void wxBitmap::SetPixmap( WXPixmap pixmap )
  916. {
  917. if (!m_refData) m_refData = new wxBitmapRefData();
  918. M_BMPDATA->m_pixmap = (Pixmap)pixmap;
  919. }
  920. void wxBitmap::SetBitmap( WXPixmap bitmap )
  921. {
  922. if (!m_refData) m_refData = new wxBitmapRefData();
  923. M_BMPDATA->m_bitmap = (Pixmap)bitmap;
  924. }
  925. WXPixmap wxBitmap::GetPixmap() const
  926. {
  927. wxCHECK_MSG( IsOk(), (WXPixmap) NULL, wxT("invalid bitmap") );
  928. return (WXPixmap)M_BMPDATA->m_pixmap;
  929. }
  930. WXPixmap wxBitmap::GetBitmap() const
  931. {
  932. wxCHECK_MSG( IsOk(), (WXPixmap) NULL, wxT("invalid bitmap") );
  933. return (WXPixmap)M_BMPDATA->m_bitmap;
  934. }
  935. WXPixmap wxBitmap::GetDrawable() const
  936. {
  937. wxCHECK_MSG( IsOk(), (WXPixmap) NULL, wxT("invalid bitmap") );
  938. return (WXPixmap)(M_BMPDATA->m_bpp == 1 ? M_BMPDATA->m_bitmap
  939. : M_BMPDATA->m_pixmap);
  940. }
  941. WXDisplay *wxBitmap::GetDisplay() const
  942. {
  943. wxCHECK_MSG( IsOk(), NULL, wxT("invalid bitmap") );
  944. return M_BMPDATA->m_display;
  945. }
  946. #if wxUSE_NANOX
  947. // Copy from the drawable to the wxImage
  948. bool wxGetImageFromDrawable(GR_DRAW_ID drawable, int srcX, int srcY, int width, int height, wxImage& image)
  949. {
  950. GR_SCREEN_INFO sinfo;
  951. int x, y;
  952. GR_PIXELVAL *pixels;
  953. GR_PALETTE* palette = NULL;
  954. unsigned char rgb[3], *pp;
  955. GrGetScreenInfo(&sinfo);
  956. if (sinfo.pixtype == MWPF_PALETTE) {
  957. if(!(palette = (GR_PALETTE*) malloc(sizeof(GR_PALETTE)))) {
  958. return false;
  959. }
  960. GrGetSystemPalette(palette);
  961. }
  962. if(!(pixels = (GR_PIXELVAL*) malloc(sizeof(GR_PIXELVAL) * width * height)))
  963. {
  964. return false;
  965. }
  966. image.Create(width, height);
  967. GrReadArea(drawable, srcX, srcY, width, height,
  968. pixels);
  969. for(x = 0; x < sinfo.cols; x++) {
  970. pp = (unsigned char *)pixels +
  971. ((x + (y * sinfo.cols)) *
  972. sizeof(GR_PIXELVAL));
  973. switch(sinfo.pixtype) {
  974. /* FIXME: These may need modifying on big endian. */
  975. case MWPF_TRUECOLOR0888:
  976. case MWPF_TRUECOLOR888:
  977. rgb[0] = pp[2];
  978. rgb[1] = pp[1];
  979. rgb[2] = pp[0];
  980. break;
  981. case MWPF_PALETTE:
  982. rgb[0] = palette->palette[pp[0]].r;
  983. rgb[1] = palette->palette[pp[0]].g;
  984. rgb[2] = palette->palette[pp[0]].b;
  985. break;
  986. case MWPF_TRUECOLOR565:
  987. rgb[0] = pp[1] & 0xf8;
  988. rgb[1] = ((pp[1] & 0x07) << 5) |
  989. ((pp[0] & 0xe0) >> 3);
  990. rgb[2] = (pp[0] & 0x1f) << 3;
  991. break;
  992. case MWPF_TRUECOLOR555:
  993. rgb[0] = (pp[1] & 0x7c) << 1;
  994. rgb[1] = ((pp[1] & 0x03) << 6) |
  995. ((pp[0] & 0xe0) >> 2);
  996. rgb[2] = (pp[0] & 0x1f) << 3;
  997. break;
  998. case MWPF_TRUECOLOR332:
  999. rgb[0] = pp[0] & 0xe0;
  1000. rgb[1] = (pp[0] & 0x1c) << 3;
  1001. rgb[2] = (pp[0] & 0x03) << 6;
  1002. break;
  1003. default:
  1004. fprintf(stderr, "Unsupported pixel "
  1005. "format\n");
  1006. return 1;
  1007. }
  1008. image.SetRGB(x, y, rgb[0], rgb[1], rgb[2]);
  1009. }
  1010. free(pixels);
  1011. if(palette) free(palette);
  1012. return true;
  1013. }
  1014. #if 0
  1015. int GrGetPixelColor(GR_SCREEN_INFO* sinfo, GR_PALETTE* palette, GR_PIXELVAL pixel,
  1016. unsigned char* red, unsigned char* green, unsigned char* blue)
  1017. {
  1018. unsigned char rgb[3], *pp;
  1019. pp = (unsigned char*) & pixel ;
  1020. switch (sinfo.pixtype)
  1021. {
  1022. /* FIXME: These may need modifying on big endian. */
  1023. case MWPF_TRUECOLOR0888:
  1024. case MWPF_TRUECOLOR888:
  1025. rgb[0] = pp[2];
  1026. rgb[1] = pp[1];
  1027. rgb[2] = pp[0];
  1028. break;
  1029. case MWPF_PALETTE:
  1030. rgb[0] = palette->palette[pp[0]].r;
  1031. rgb[1] = palette->palette[pp[0]].g;
  1032. rgb[2] = palette->palette[pp[0]].b;
  1033. break;
  1034. case MWPF_TRUECOLOR565:
  1035. rgb[0] = pp[1] & 0xf8;
  1036. rgb[1] = ((pp[1] & 0x07) << 5) |
  1037. ((pp[0] & 0xe0) >> 3);
  1038. rgb[2] = (pp[0] & 0x1f) << 3;
  1039. break;
  1040. case MWPF_TRUECOLOR555:
  1041. rgb[0] = (pp[1] & 0x7c) << 1;
  1042. rgb[1] = ((pp[1] & 0x03) << 6) |
  1043. ((pp[0] & 0xe0) >> 2);
  1044. rgb[2] = (pp[0] & 0x1f) << 3;
  1045. break;
  1046. case MWPF_TRUECOLOR332:
  1047. rgb[0] = pp[0] & 0xe0;
  1048. rgb[1] = (pp[0] & 0x1c) << 3;
  1049. rgb[2] = (pp[0] & 0x03) << 6;
  1050. break;
  1051. default:
  1052. fprintf(stderr, "Unsupported pixel format\n");
  1053. return 0;
  1054. }
  1055. *(red) = rgb[0];
  1056. *(green) = rgb[1];
  1057. *(blue) = rgb[2];
  1058. return 1;
  1059. }
  1060. #endif
  1061. #endif
  1062. // wxUSE_NANOX
  1063. // ============================================================================
  1064. // Bitmap handlers
  1065. // ============================================================================
  1066. #define M_BMPHANDLERDATA ((wxBitmapRefData *)bitmap->GetRefData())
  1067. #if wxUSE_XPM
  1068. #if wxHAVE_LIB_XPM || wxUSE_STREAMS
  1069. // ----------------------------------------------------------------------------
  1070. // wxXPMFileHandler
  1071. // ----------------------------------------------------------------------------
  1072. class wxXPMFileHandler : public wxBitmapHandler
  1073. {
  1074. public:
  1075. wxXPMFileHandler()
  1076. {
  1077. SetName( wxT("XPM file") );
  1078. SetExtension( wxT("xpm") );
  1079. SetType( wxBITMAP_TYPE_XPM );
  1080. };
  1081. virtual bool LoadFile(wxBitmap *bitmap, const wxString& name,
  1082. wxBitmapType flags,
  1083. int desiredWidth, int desiredHeight);
  1084. virtual bool SaveFile(const wxBitmap *bitmap, const wxString& name,
  1085. wxBitmapType type,
  1086. const wxPalette *palette = NULL) const;
  1087. virtual bool Create(wxBitmap *WXUNUSED(bitmap),
  1088. const void* WXUNUSED(data),
  1089. wxBitmapType WXUNUSED(flags),
  1090. int WXUNUSED(width),
  1091. int WXUNUSED(height),
  1092. int WXUNUSED(depth) = 1)
  1093. { return false; }
  1094. DECLARE_DYNAMIC_CLASS(wxXPMFileHandler)
  1095. };
  1096. IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler)
  1097. bool wxXPMFileHandler::LoadFile(wxBitmap *bitmap,
  1098. const wxString& name,
  1099. wxBitmapType WXUNUSED(flags),
  1100. int WXUNUSED(desiredWidth),
  1101. int WXUNUSED(desiredHeight))
  1102. {
  1103. #if wxHAVE_LIB_XPM
  1104. if (!bitmap->GetRefData())
  1105. bitmap->SetRefData( new wxBitmapRefData() );
  1106. M_BMPHANDLERDATA->m_display = wxGlobalDisplay();
  1107. Display *xdisplay = (Display*) M_BMPHANDLERDATA->m_display;
  1108. int xscreen = DefaultScreen( xdisplay );
  1109. Window xroot = RootWindow( xdisplay, xscreen );
  1110. int bpp = DefaultDepth( xdisplay, xscreen );
  1111. XpmAttributes xpmAttr;
  1112. xpmAttr.valuemask = XpmReturnInfos; // nothing yet, but get infos back
  1113. Pixmap pixmap;
  1114. Pixmap mask = 0;
  1115. int ErrorStatus = XpmReadFileToPixmap( xdisplay, xroot,
  1116. (char*) ((const char*) name.c_str()),
  1117. &pixmap, &mask, &xpmAttr);
  1118. if (ErrorStatus == XpmSuccess)
  1119. {
  1120. M_BMPHANDLERDATA->m_width = xpmAttr.width;
  1121. M_BMPHANDLERDATA->m_height = xpmAttr.height;
  1122. M_BMPHANDLERDATA->m_bpp = bpp; // mono as well?
  1123. XpmFreeAttributes(&xpmAttr);
  1124. M_BMPHANDLERDATA->m_bitmap = (Pixmap) pixmap;
  1125. if (mask)
  1126. {
  1127. M_BMPHANDLERDATA->m_mask = new wxMask;
  1128. M_BMPHANDLERDATA->m_mask->SetBitmap( (WXPixmap) mask );
  1129. M_BMPHANDLERDATA->m_mask->SetDisplay( xdisplay );
  1130. }
  1131. }
  1132. else
  1133. {
  1134. UnRef();
  1135. return false;
  1136. }
  1137. return true;
  1138. #elif wxUSE_STREAMS
  1139. wxXPMDecoder decoder;
  1140. wxFileInputStream stream(name);
  1141. if (stream.IsOk())
  1142. {
  1143. wxImage image(decoder.ReadFile(stream));
  1144. return image.IsOk() && bitmap->CreateFromImage(image);
  1145. }
  1146. return false;
  1147. #else // !wxHAVE_LIB_XPM && !wxUSE_STREAMS
  1148. return false;
  1149. #endif // wxHAVE_LIB_XPM / wxUSE_STREAMS
  1150. }
  1151. bool wxXPMFileHandler::SaveFile(const wxBitmap *bitmap,
  1152. const wxString& name,
  1153. wxBitmapType type,
  1154. const wxPalette *WXUNUSED(palette)) const
  1155. {
  1156. wxImage image(bitmap->ConvertToImage());
  1157. if (image.IsOk())
  1158. return image.SaveFile( name, type );
  1159. return false;
  1160. }
  1161. #endif // wxHAVE_LIB_XPM || wxUSE_STREAMS
  1162. // ----------------------------------------------------------------------------
  1163. // wxXPMDataHandler
  1164. // ----------------------------------------------------------------------------
  1165. class wxXPMDataHandler : public wxBitmapHandler
  1166. {
  1167. DECLARE_DYNAMIC_CLASS(wxXPMDataHandler)
  1168. public:
  1169. wxXPMDataHandler()
  1170. {
  1171. SetName( wxT("XPM data") );
  1172. SetExtension( wxT("xpm") );
  1173. SetType( wxBITMAP_TYPE_XPM_DATA );
  1174. };
  1175. virtual bool LoadFile(wxBitmap *WXUNUSED(bitmap),
  1176. const wxString& WXUNUSED(name),
  1177. wxBitmapType WXUNUSED(flags),
  1178. int WXUNUSED(desiredWidth),
  1179. int WXUNUSED(desiredHeight))
  1180. { return false; }
  1181. virtual bool SaveFile(const wxBitmap *WXUNUSED(bitmap),
  1182. const wxString& WXUNUSED(name),
  1183. wxBitmapType WXUNUSED(type),
  1184. const wxPalette *WXUNUSED(palette) = NULL) const
  1185. { return false; }
  1186. virtual bool Create(wxBitmap *bitmap, const void* data, wxBitmapType flags,
  1187. int width, int height, int depth = 1);
  1188. };
  1189. IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler)
  1190. bool wxXPMDataHandler::Create(wxBitmap *bitmap, const void* bits,
  1191. wxBitmapType WXUNUSED(flags),
  1192. int WXUNUSED(width), int WXUNUSED(height), int WXUNUSED(depth))
  1193. {
  1194. #if wxHAVE_LIB_XPM
  1195. wxCHECK_MSG( bits != NULL, false, wxT("invalid bitmap data") );
  1196. if (!bitmap->GetRefData())
  1197. bitmap->SetRefData( new wxBitmapRefData() );
  1198. M_BMPHANDLERDATA->m_display = wxGlobalDisplay();
  1199. Display *xdisplay = (Display*) M_BMPHANDLERDATA->m_display;
  1200. int xscreen = DefaultScreen( xdisplay );
  1201. Window xroot = RootWindow( xdisplay, xscreen );
  1202. int bpp = DefaultDepth( xdisplay, xscreen );
  1203. XpmAttributes xpmAttr;
  1204. xpmAttr.valuemask = XpmReturnInfos; // nothing yet, but get infos back
  1205. Pixmap pixmap = 0;
  1206. Pixmap mask = 0;
  1207. int ErrorStatus = XpmCreatePixmapFromData( xdisplay, xroot, (char**) bits,
  1208. &pixmap, &mask, &xpmAttr );
  1209. if (ErrorStatus == XpmSuccess)
  1210. {
  1211. M_BMPHANDLERDATA->m_width = xpmAttr.width;
  1212. M_BMPHANDLERDATA->m_height = xpmAttr.height;
  1213. M_BMPHANDLERDATA->m_bpp = bpp; // mono as well?
  1214. #if wxDEBUG_LEVEL
  1215. unsigned int depthRet;
  1216. int xRet, yRet;
  1217. unsigned int widthRet, heightRet, borderWidthRet;
  1218. XGetGeometry( xdisplay, pixmap, &xroot, &xRet, &yRet,
  1219. &widthRet, &heightRet, &borderWidthRet, &depthRet);
  1220. wxASSERT_MSG( bpp == (int)depthRet, wxT("colour depth mismatch") );
  1221. #endif // wxDEBUG_LEVEL
  1222. XpmFreeAttributes(&xpmAttr);
  1223. M_BMPHANDLERDATA->m_pixmap = (Pixmap) pixmap;
  1224. if (mask)
  1225. {
  1226. M_BMPHANDLERDATA->m_mask = new wxMask;
  1227. M_BMPHANDLERDATA->m_mask->SetBitmap( (WXPixmap) mask );
  1228. M_BMPHANDLERDATA->m_mask->SetDisplay( xdisplay );
  1229. }
  1230. return true;
  1231. }
  1232. else
  1233. {
  1234. bitmap->UnRef();
  1235. return false;
  1236. }
  1237. #else // !wxHAVE_LIB_XPM
  1238. wxXPMDecoder decoder;
  1239. wxImage image(decoder.ReadData((const char **)bits));
  1240. return image.IsOk() && bitmap->CreateFromImage(image);
  1241. #endif // wxHAVE_LIB_XPM/!wxHAVE_LIB_XPM
  1242. }
  1243. #endif // wxUSE_XPM
  1244. // ----------------------------------------------------------------------------
  1245. // wxXBMDataHandler
  1246. // ----------------------------------------------------------------------------
  1247. class WXDLLEXPORT wxXBMDataHandler: public wxBitmapHandler
  1248. {
  1249. DECLARE_DYNAMIC_CLASS(wxXBMDataHandler)
  1250. public:
  1251. inline wxXBMDataHandler()
  1252. {
  1253. SetName( wxT("XBM data") );
  1254. SetExtension( wxT("xbm") );
  1255. SetType( wxBITMAP_TYPE_XBM_DATA );
  1256. };
  1257. virtual bool LoadFile(wxBitmap *WXUNUSED(bitmap),
  1258. const wxString& WXUNUSED(name),
  1259. wxBitmapType WXUNUSED(flags),
  1260. int WXUNUSED(desiredWidth),
  1261. int WXUNUSED(desiredHeight))
  1262. { return false; }
  1263. virtual bool SaveFile(const wxBitmap *WXUNUSED(bitmap),
  1264. const wxString& WXUNUSED(name),
  1265. wxBitmapType WXUNUSED(type),
  1266. const wxPalette *WXUNUSED(palette) = NULL) const
  1267. { return false; }
  1268. virtual bool Create(wxBitmap *bitmap, const void* data, wxBitmapType type,
  1269. int width, int height, int depth = 1);
  1270. };
  1271. IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler, wxBitmapHandler)
  1272. bool wxXBMDataHandler::Create( wxBitmap *bitmap, const void* bits,
  1273. wxBitmapType WXUNUSED(type),
  1274. int width, int height, int WXUNUSED(depth))
  1275. {
  1276. #if !wxUSE_NANOX
  1277. if (!bitmap->GetRefData())
  1278. bitmap->SetRefData( new wxBitmapRefData() );
  1279. M_BMPHANDLERDATA->m_display = wxGlobalDisplay();
  1280. Display *xdisplay = (Display*) M_BMPHANDLERDATA->m_display;
  1281. int xscreen = DefaultScreen( xdisplay );
  1282. Window xroot = RootWindow( xdisplay, xscreen );
  1283. M_BMPHANDLERDATA->m_mask = NULL;
  1284. M_BMPHANDLERDATA->m_bitmap =
  1285. XCreateBitmapFromData(xdisplay, xroot,
  1286. (char *) bits, width, height );
  1287. M_BMPHANDLERDATA->m_width = width;
  1288. M_BMPHANDLERDATA->m_height = height;
  1289. M_BMPHANDLERDATA->m_bpp = 1;
  1290. return true;
  1291. #else
  1292. wxCHECK_MSG( M_BMPHANDLERDATA->m_bitmap, false,
  1293. wxT("couldn't create bitmap") );
  1294. #endif
  1295. }
  1296. void wxBitmap::InitStandardHandlers()
  1297. {
  1298. AddHandler(new wxXBMDataHandler);
  1299. #if wxUSE_XPM
  1300. #if wxHAVE_LIB_XPM || wxUSE_STREAMS
  1301. AddHandler(new wxXPMFileHandler);
  1302. #endif
  1303. AddHandler(new wxXPMDataHandler);
  1304. #endif
  1305. }