PageRenderTime 50ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/ExtLibs/wxWidgets/src/cocoa/bitmap.mm

https://bitbucket.org/lennonchan/cafu
Objective C++ | 725 lines | 552 code | 105 blank | 68 comment | 64 complexity | 5f70702e757a6a80b2d89006335f600e MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: src/cocoa/bitmap.mm
  3. // Purpose: wxBitmap
  4. // Author: David Elliott
  5. // Modified by:
  6. // Created: 2003/07/19
  7. // RCS-ID: $Id$
  8. // Copyright: (c) 2003 David Elliott
  9. // Licence: wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11. #include "wx/wxprec.h"
  12. #include "wx/bitmap.h"
  13. #ifndef WX_PRECOMP
  14. #include "wx/log.h"
  15. #include "wx/utils.h"
  16. #include "wx/palette.h"
  17. #include "wx/icon.h"
  18. #include "wx/colour.h"
  19. #include "wx/image.h"
  20. #endif //WX_PRECOMP
  21. #include "wx/xpmdecod.h"
  22. #include "wx/rawbmp.h"
  23. #include "wx/cocoa/autorelease.h"
  24. #include "wx/cocoa/string.h"
  25. #include "wx/cocoa/ObjcRef.h"
  26. #import <AppKit/NSBitmapImageRep.h>
  27. #import <AppKit/NSGraphics.h>
  28. #import <AppKit/NSImage.h>
  29. #import <AppKit/NSColor.h>
  30. IMPLEMENT_ABSTRACT_CLASS(wxBitmapHandler, wxBitmapHandlerBase)
  31. // ========================================================================
  32. // wxBitmapRefData
  33. // ========================================================================
  34. class wxBitmapRefData: public wxGDIRefData
  35. {
  36. friend class wxBitmap;
  37. public:
  38. wxBitmapRefData();
  39. wxBitmapRefData( const wxBitmapRefData& data );
  40. virtual ~wxBitmapRefData();
  41. virtual bool IsOk() const { return m_ok; }
  42. protected:
  43. int m_width;
  44. int m_height;
  45. int m_depth;
  46. bool m_ok;
  47. int m_numColors;
  48. wxPalette m_bitmapPalette;
  49. int m_quality;
  50. WX_NSBitmapImageRep m_cocoaNSBitmapImageRep;
  51. wxMask *m_bitmapMask; // Optional mask
  52. };
  53. wxBitmapRefData::wxBitmapRefData()
  54. {
  55. m_ok = FALSE;
  56. m_width = 0;
  57. m_height = 0;
  58. m_depth = 0;
  59. m_quality = 0;
  60. m_numColors = 0;
  61. m_cocoaNSBitmapImageRep = nil;
  62. m_bitmapMask = NULL;
  63. }
  64. wxBitmapRefData::wxBitmapRefData( const wxBitmapRefData& data)
  65. {
  66. wxAutoNSAutoreleasePool pool;
  67. m_width = data.m_width;
  68. m_height = data.m_height;
  69. m_depth = data.m_depth;
  70. m_ok = data.m_ok;
  71. m_numColors = data.m_numColors;
  72. m_bitmapPalette = data.m_bitmapPalette;
  73. m_quality = data.m_quality;
  74. m_cocoaNSBitmapImageRep = wxGCSafeRetain([[data.m_cocoaNSBitmapImageRep copyWithZone:nil] autorelease]);
  75. m_bitmapMask = data.m_bitmapMask?new wxMask(*data.m_bitmapMask):NULL;
  76. }
  77. wxBitmapRefData::~wxBitmapRefData()
  78. {
  79. wxGCSafeRelease(m_cocoaNSBitmapImageRep);
  80. m_cocoaNSBitmapImageRep = NULL;
  81. delete m_bitmapMask;
  82. m_bitmapMask = NULL;
  83. }
  84. // ========================================================================
  85. // wxBitmap
  86. // ========================================================================
  87. #define M_BITMAPDATA ((wxBitmapRefData *)m_refData)
  88. IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
  89. wxBitmap::wxBitmap()
  90. {
  91. m_refData = NULL;
  92. }
  93. wxBitmap::~wxBitmap()
  94. {
  95. }
  96. wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits)
  97. {
  98. m_refData = new wxBitmapRefData;
  99. M_BITMAPDATA->m_width = the_width ;
  100. M_BITMAPDATA->m_height = the_height ;
  101. M_BITMAPDATA->m_depth = no_bits ;
  102. M_BITMAPDATA->m_numColors = 0;
  103. /* TODO: create the bitmap from data */
  104. }
  105. wxBitmap::wxBitmap(NSImage* cocoaNSImage)
  106. {
  107. (void) Create(cocoaNSImage);
  108. }
  109. wxBitmap::wxBitmap(NSBitmapImageRep* cocoaNSBitmapImageRep)
  110. {
  111. (void) Create(cocoaNSBitmapImageRep);
  112. }
  113. wxBitmap::wxBitmap(const void* data, wxBitmapType type, int width, int height, int depth)
  114. {
  115. (void) Create(data, type, width, height, depth);
  116. }
  117. wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type)
  118. {
  119. LoadFile(filename, type);
  120. }
  121. wxGDIRefData *wxBitmap::CreateGDIRefData() const
  122. {
  123. return new wxBitmapRefData;
  124. }
  125. wxGDIRefData *wxBitmap::CloneGDIRefData(const wxGDIRefData *data) const
  126. {
  127. return new wxBitmapRefData(*(wxBitmapRefData*)data);
  128. }
  129. WX_NSBitmapImageRep wxBitmap::GetNSBitmapImageRep()
  130. {
  131. if(!M_BITMAPDATA)
  132. return NULL;
  133. return M_BITMAPDATA->m_cocoaNSBitmapImageRep;
  134. }
  135. WX_NSImage wxBitmap::GetNSImage(bool useMask) const
  136. {
  137. if(!IsOk())
  138. return nil;
  139. NSImage *nsimage = [[[NSImage alloc]
  140. initWithSize:NSMakeSize(GetWidth(), GetHeight())] autorelease];
  141. if(!nsimage)
  142. return nil;
  143. [nsimage addRepresentation: M_BITMAPDATA->m_cocoaNSBitmapImageRep];
  144. if(useMask && GetMask())
  145. {
  146. // Show before/after to prove that the bitmap itself is not changed
  147. // even though we just composited onto the NSImage
  148. wxLogTrace(wxTRACE_COCOA,wxT("Before: bpp=%d"),[M_BITMAPDATA->m_cocoaNSBitmapImageRep bitsPerPixel]);
  149. NSImage *maskImage = [[NSImage alloc]
  150. initWithSize:NSMakeSize(GetWidth(), GetHeight())];
  151. [maskImage addRepresentation: GetMask()->GetNSBitmapImageRep()];
  152. [nsimage lockFocus];
  153. [maskImage compositeToPoint:NSZeroPoint operation:NSCompositeDestinationIn];
  154. [nsimage unlockFocus];
  155. [maskImage release];
  156. wxLogTrace(wxTRACE_COCOA,wxT("After: bpp=%d"),[M_BITMAPDATA->m_cocoaNSBitmapImageRep bitsPerPixel]);
  157. }
  158. return nsimage;
  159. }
  160. void wxBitmap::SetNSBitmapImageRep(WX_NSBitmapImageRep bitmapImageRep)
  161. {
  162. if(!M_BITMAPDATA)
  163. return;
  164. // NOTE: No checking is done to make sure width/height agree
  165. wxGCSafeRetain(bitmapImageRep);
  166. wxGCSafeRelease(M_BITMAPDATA->m_cocoaNSBitmapImageRep);
  167. M_BITMAPDATA->m_cocoaNSBitmapImageRep = bitmapImageRep;
  168. }
  169. void wxBitmap::SetWidth(int w)
  170. {
  171. if (!M_BITMAPDATA)
  172. m_refData = new wxBitmapRefData;
  173. M_BITMAPDATA->m_width = w;
  174. }
  175. void wxBitmap::SetHeight(int h)
  176. {
  177. if (!M_BITMAPDATA)
  178. m_refData = new wxBitmapRefData;
  179. M_BITMAPDATA->m_height = h;
  180. }
  181. void wxBitmap::SetDepth(int d)
  182. {
  183. if (!M_BITMAPDATA)
  184. m_refData = new wxBitmapRefData;
  185. M_BITMAPDATA->m_depth = d;
  186. }
  187. void wxBitmap::SetQuality(int q)
  188. {
  189. if (!M_BITMAPDATA)
  190. m_refData = new wxBitmapRefData;
  191. M_BITMAPDATA->m_quality = q;
  192. }
  193. void wxBitmap::SetOk(bool isOk)
  194. {
  195. if (!M_BITMAPDATA)
  196. m_refData = new wxBitmapRefData;
  197. M_BITMAPDATA->m_ok = isOk;
  198. }
  199. void wxBitmap::SetPalette(const wxPalette& palette)
  200. {
  201. if (!M_BITMAPDATA)
  202. m_refData = new wxBitmapRefData;
  203. M_BITMAPDATA->m_bitmapPalette = palette ;
  204. }
  205. void wxBitmap::SetMask(wxMask *mask)
  206. {
  207. if (!M_BITMAPDATA)
  208. m_refData = new wxBitmapRefData;
  209. M_BITMAPDATA->m_bitmapMask = mask ;
  210. }
  211. wxPalette* wxBitmap::GetPalette() const
  212. {
  213. if(!m_refData)
  214. return NULL;
  215. return &M_BITMAPDATA->m_bitmapPalette;
  216. }
  217. wxMask* wxBitmap::GetMask() const
  218. {
  219. if(!m_refData)
  220. return NULL;
  221. return M_BITMAPDATA->m_bitmapMask;
  222. }
  223. int wxBitmap::GetDepth() const
  224. {
  225. if(!m_refData)
  226. return 0;
  227. return M_BITMAPDATA->m_depth;
  228. }
  229. int wxBitmap::GetWidth() const
  230. {
  231. if(!m_refData)
  232. return 0;
  233. return M_BITMAPDATA->m_width;
  234. }
  235. int wxBitmap::GetHeight() const
  236. {
  237. if(!m_refData)
  238. return 0;
  239. return M_BITMAPDATA->m_height;
  240. }
  241. bool wxBitmap::Create(int w, int h, int d)
  242. {
  243. wxAutoNSAutoreleasePool pool;
  244. UnRef();
  245. m_refData = new wxBitmapRefData;
  246. M_BITMAPDATA->m_width = w;
  247. M_BITMAPDATA->m_height = h;
  248. M_BITMAPDATA->m_depth = d;
  249. /* TODO: create new bitmap */
  250. M_BITMAPDATA->m_cocoaNSBitmapImageRep = wxGCSafeRetain([[[NSBitmapImageRep alloc]
  251. initWithBitmapDataPlanes: NULL
  252. pixelsWide: w
  253. pixelsHigh: h
  254. bitsPerSample: 8
  255. samplesPerPixel: 3
  256. hasAlpha: NO
  257. isPlanar: NO
  258. colorSpaceName: NSCalibratedRGBColorSpace
  259. bytesPerRow: 0 // NOTE: Contrary to Apple documentation Mac OS
  260. // 10.4 will add padding bytes when 0 is used here
  261. bitsPerPixel: 0] autorelease]);
  262. wxLogTrace(wxTRACE_COCOA,wxT("M_BITMAPDATA=%p NSBitmapImageRep bitmapData=%p"), M_BITMAPDATA, [M_BITMAPDATA->m_cocoaNSBitmapImageRep bitmapData]);
  263. M_BITMAPDATA->m_ok = true;
  264. M_BITMAPDATA->m_numColors = 0;
  265. M_BITMAPDATA->m_quality = 0;
  266. M_BITMAPDATA->m_bitmapMask = NULL;
  267. return M_BITMAPDATA->m_ok;
  268. }
  269. bool wxBitmap::LoadFile(const wxString& filename, wxBitmapType type)
  270. {
  271. wxAutoNSAutoreleasePool pool;
  272. UnRef();
  273. m_refData = new wxBitmapRefData;
  274. NSBitmapImageRep *imageRep = [NSBitmapImageRep
  275. imageRepWithContentsOfFile:wxNSStringWithWxString(filename)];
  276. if(imageRep)
  277. {
  278. M_BITMAPDATA->m_width = [imageRep pixelsWide];
  279. M_BITMAPDATA->m_height = [imageRep pixelsHigh];
  280. M_BITMAPDATA->m_depth = 24; // FIXME
  281. M_BITMAPDATA->m_ok = true;
  282. M_BITMAPDATA->m_numColors = 0;
  283. M_BITMAPDATA->m_quality = 0;
  284. M_BITMAPDATA->m_cocoaNSBitmapImageRep = wxGCSafeRetain(imageRep);
  285. M_BITMAPDATA->m_bitmapMask = NULL;
  286. return true;
  287. }
  288. wxImage image;
  289. if(!image.LoadFile(filename,type))
  290. return false;
  291. if(!image.IsOk())
  292. return false;
  293. *this = wxBitmap(image);
  294. return true;
  295. }
  296. bool wxBitmap::Create(NSImage* cocoaNSImage)
  297. {
  298. wxAutoNSAutoreleasePool pool;
  299. NSBitmapImageRep *bitmapImageRep = [NSBitmapImageRep imageRepWithData:[cocoaNSImage TIFFRepresentation]];
  300. return Create(bitmapImageRep);
  301. }
  302. bool wxBitmap::Create(NSBitmapImageRep *imageRep)
  303. {
  304. UnRef();
  305. m_refData = new wxBitmapRefData;
  306. if(imageRep != nil)
  307. {
  308. M_BITMAPDATA->m_width = [imageRep pixelsWide];
  309. M_BITMAPDATA->m_height = [imageRep pixelsHigh];
  310. M_BITMAPDATA->m_depth = [imageRep bitsPerPixel];
  311. M_BITMAPDATA->m_ok = true;
  312. M_BITMAPDATA->m_numColors = 0;
  313. M_BITMAPDATA->m_quality = 0;
  314. M_BITMAPDATA->m_cocoaNSBitmapImageRep = wxGCSafeRetain(imageRep);
  315. M_BITMAPDATA->m_bitmapMask = NULL;
  316. return true;
  317. }
  318. else
  319. return false;
  320. }
  321. bool wxBitmap::Create(const void* data, wxBitmapType type, int width, int height, int depth)
  322. {
  323. UnRef();
  324. m_refData = new wxBitmapRefData;
  325. return false;
  326. }
  327. bool wxBitmap::SaveFile(const wxString& filename, wxBitmapType type, const wxPalette *palette) const
  328. {
  329. return false;
  330. }
  331. bool wxBitmap::CopyFromIcon(const wxIcon& icon)
  332. {
  333. // Pool here due to lack of one during wx init phase
  334. wxAutoNSAutoreleasePool pool;
  335. UnRef();
  336. if(!icon.GetNSImage());
  337. [icon.GetNSImage() lockFocus];
  338. NSRect imageRect;
  339. imageRect.origin.x = imageRect.origin.y = 0.0;
  340. imageRect.size = [icon.GetNSImage() size];
  341. NSBitmapImageRep *newBitmapRep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect:imageRect] autorelease];
  342. [icon.GetNSImage() unlockFocus];
  343. if(!newBitmapRep)
  344. return false;
  345. m_refData = new wxBitmapRefData;
  346. M_BITMAPDATA->m_cocoaNSBitmapImageRep = wxGCSafeRetain(newBitmapRep);
  347. M_BITMAPDATA->m_width = [newBitmapRep pixelsWide];
  348. M_BITMAPDATA->m_height = [newBitmapRep pixelsHigh];
  349. M_BITMAPDATA->m_depth = [newBitmapRep bitsPerSample]*[newBitmapRep samplesPerPixel];
  350. M_BITMAPDATA->m_ok = true;
  351. M_BITMAPDATA->m_numColors = 0;
  352. M_BITMAPDATA->m_quality = 0;
  353. M_BITMAPDATA->m_bitmapMask = NULL;
  354. return true;
  355. }
  356. wxBitmap wxBitmap::GetSubBitmap(const wxRect& rect) const
  357. {
  358. wxAutoNSAutoreleasePool pool;
  359. if(!IsOk())
  360. return wxNullBitmap;
  361. NSImage *nsimage = GetNSImage(false);
  362. [nsimage lockFocus];
  363. NSRect imageRect = {{0,0}, [nsimage size]};
  364. imageRect.origin.x = imageRect.size.width * rect.x / GetWidth();
  365. imageRect.origin.y = imageRect.size.height * rect.y / GetHeight();
  366. imageRect.size.width *= static_cast<CGFloat>(rect.width) / GetWidth();
  367. imageRect.size.height *= static_cast<CGFloat>(rect.height) / GetHeight();
  368. NSBitmapImageRep *newBitmapRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:imageRect];
  369. [nsimage unlockFocus];
  370. wxBitmap newBitmap(newBitmapRep);
  371. return (newBitmap);
  372. }
  373. wxImage wxBitmap::ConvertToImage() const
  374. {
  375. wxAutoNSAutoreleasePool pool;
  376. if(!IsOk())
  377. return /*wxImage(5,5)*/wxNullImage;
  378. NSImage *nsimage = GetNSImage(false /* don't use mask */);
  379. wxImage newImage(M_BITMAPDATA->m_width,M_BITMAPDATA->m_height);
  380. [nsimage lockFocus];
  381. for(int i=0; i < M_BITMAPDATA->m_width; i++)
  382. {
  383. // Don't let the pool get too big as you'll notice we're creating
  384. // two autoreleased NSColor objects with every iteration.
  385. wxAutoNSAutoreleasePool loopPool;
  386. for(int j=0; j < M_BITMAPDATA->m_height; j++)
  387. {
  388. NSColor *pixelColor = NSReadPixel(NSMakePoint(i,M_BITMAPDATA->m_height - j - 1));
  389. NSColor *color = [pixelColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
  390. newImage.SetRGB(i,j,int([color redComponent]*255.0), int([color greenComponent]*255.0), int([color blueComponent]*255.0));
  391. }
  392. }
  393. [nsimage unlockFocus];
  394. return newImage;
  395. }
  396. bool wxBitmap::CreateFromImage(const wxImage& image, int depth)
  397. {
  398. wxAutoNSAutoreleasePool pool;
  399. UnRef();
  400. wxCHECK_MSG(image.IsOk(), false, wxT("invalid image"));
  401. wxCHECK_MSG(depth == -1 || depth == 1, false, wxT("invalid bitmap depth"));
  402. m_refData = new wxBitmapRefData();
  403. M_BITMAPDATA->m_width = image.GetWidth();
  404. M_BITMAPDATA->m_height = image.GetHeight();
  405. NSBitmapImageRep *bitmapImage = [[[NSBitmapImageRep alloc]
  406. initWithBitmapDataPlanes: NULL
  407. pixelsWide: image.GetWidth()
  408. pixelsHigh: image.GetHeight()
  409. bitsPerSample: 8
  410. samplesPerPixel: 3
  411. hasAlpha: NO
  412. isPlanar: NO
  413. colorSpaceName: NSCalibratedRGBColorSpace
  414. bytesPerRow: image.GetWidth()*3
  415. bitsPerPixel: 0] autorelease];
  416. // TODO: Specify bytesPerRow:0 and then use [bitmapImage bytesPerRow]
  417. // so that the rows are aligned suitably for altivec by the OS (Tiger)
  418. const int numBytes = image.GetWidth()*image.GetHeight()*3;
  419. memcpy([bitmapImage bitmapData], image.GetData(), numBytes);
  420. // TODO: Alpha and convert to desired depth
  421. M_BITMAPDATA->m_depth = 24;
  422. M_BITMAPDATA->m_ok = true;
  423. M_BITMAPDATA->m_numColors = 0;
  424. M_BITMAPDATA->m_quality = 0;
  425. M_BITMAPDATA->m_cocoaNSBitmapImageRep = wxGCSafeRetain(bitmapImage);
  426. M_BITMAPDATA->m_bitmapMask = new wxMask(*this,wxColour(image.GetMaskRed(),image.GetMaskGreen(),image.GetMaskBlue()));
  427. return true;
  428. }
  429. void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp)
  430. {
  431. if(!IsOk())
  432. return NULL;
  433. NSBitmapImageRep *bitmapRep = M_BITMAPDATA->m_cocoaNSBitmapImageRep;
  434. if(!bitmapRep)
  435. return NULL;
  436. if([bitmapRep bitsPerPixel]!=bpp)
  437. {
  438. wxFAIL_MSG( wxT("incorrect bitmap type in wxBitmap::GetRawData()") );
  439. return NULL;
  440. }
  441. data.m_width = [bitmapRep pixelsWide];
  442. data.m_height = [bitmapRep pixelsHigh];
  443. data.m_stride = [bitmapRep bytesPerRow];
  444. return [bitmapRep bitmapData];
  445. // NOTE: It is up to the user to make sure they used the proper
  446. // pixel format class that details what is actually inside the pixels
  447. // We can only check to make sure that the total number of bits per
  448. // pixel are being iterated over properly
  449. // NSBitmapImageRep can contain grayscale or CMYK data and
  450. // wxPixelDataBase doesn't really define the color format
  451. }
  452. void wxBitmap::UngetRawData(wxPixelDataBase& data)
  453. { // TODO
  454. }
  455. // ========================================================================
  456. // wxMask
  457. // ========================================================================
  458. IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
  459. wxMask::wxMask()
  460. {
  461. m_cocoaNSBitmapImageRep = nil;
  462. }
  463. // Construct a mask from a bitmap and a colour indicating
  464. // the transparent area
  465. wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
  466. {
  467. m_cocoaNSBitmapImageRep = nil;
  468. Create(bitmap, colour);
  469. }
  470. // Construct a mask from a bitmap and a palette index indicating
  471. // the transparent area
  472. wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
  473. {
  474. m_cocoaNSBitmapImageRep = nil;
  475. Create(bitmap, paletteIndex);
  476. }
  477. // Construct a mask from a mono bitmap (copies the bitmap).
  478. wxMask::wxMask(const wxBitmap& bitmap)
  479. {
  480. m_cocoaNSBitmapImageRep = nil;
  481. Create(bitmap);
  482. }
  483. // Copy constructor
  484. wxMask::wxMask(const wxMask& src)
  485. : wxObject(src)
  486. , m_cocoaNSBitmapImageRep(wxGCSafeRetain(src.m_cocoaNSBitmapImageRep))
  487. {
  488. }
  489. wxMask::~wxMask()
  490. {
  491. wxGCSafeRelease(m_cocoaNSBitmapImageRep);
  492. }
  493. // Create a mask from a mono bitmap (copies the bitmap).
  494. bool wxMask::Create(const wxBitmap& bitmap)
  495. {
  496. // TODO
  497. wxLogDebug(wxT("Cannot yet create a mask from a mono bitmap"));
  498. return FALSE;
  499. }
  500. // Create a mask from a bitmap and a palette index indicating
  501. // the transparent area
  502. bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
  503. {
  504. // TODO
  505. wxLogDebug(wxT("Cannot yet create a mask from a palette bitmap"));
  506. return FALSE;
  507. }
  508. template <typename PixelData>
  509. static bool wxMask_CreateFromBitmapData(PixelData srcData, const wxColour& colour, unsigned char *dstData)
  510. {
  511. wxCHECK_MSG(dstData,false,wxT("Couldn't access mask data"));
  512. typename PixelData::Iterator p(srcData);
  513. const int nRows = srcData.GetHeight();
  514. const int nCols = srcData.GetWidth();
  515. // Total number of bytes per destination column
  516. const int dstRowLength = (nCols+7)/8;
  517. // Number of source columns that fit into a byte in the destination
  518. const int width_aligned = nCols/8*8;
  519. for(int y=0; y<nRows; ++y)
  520. {
  521. typename PixelData::Iterator rowStart(p);
  522. unsigned char *dstRow = dstData + y*dstRowLength;
  523. for(int x=0; x<width_aligned; x+=8)
  524. {
  525. unsigned char *dstByte = dstRow + x/8;
  526. *dstByte = 0;
  527. // Take source RGB, compare it with the wxColour
  528. for(int j=0; j<8; ++j, ++p)
  529. {
  530. *dstByte +=
  531. ( p.Red()!=colour.Red()
  532. || p.Green()!=colour.Green()
  533. || p.Blue()!=colour.Blue()
  534. ) << (7-j);
  535. }
  536. }
  537. // Handle the remaining 0-7 pixels in the row
  538. unsigned char *dstByte = dstRow + width_aligned/8;
  539. if(nCols%8>0)
  540. *dstByte = 0;
  541. for(int j=0; j<(nCols%8); ++j, ++p)
  542. {
  543. *dstByte +=
  544. ( p.Red()!=colour.Red()
  545. || p.Green()!=colour.Green()
  546. || p.Blue()!=colour.Blue()
  547. ) << (7-j);
  548. }
  549. p = rowStart;
  550. p.OffsetY(srcData,1);
  551. }
  552. return true;
  553. }
  554. // Create a mask from a bitmap and a colour indicating
  555. // the transparent area
  556. bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
  557. {
  558. wxAutoNSAutoreleasePool pool;
  559. if(!bitmap.IsOk())
  560. return false;
  561. int bmpWidth = bitmap.GetWidth();
  562. int bmpHeight = bitmap.GetHeight();
  563. int dstRowLength = (bmpWidth+7)/8;
  564. // Create a bitmap image rep with 1-bit per pixel data representing
  565. // the alpha channel padded such that rows end on byte boundaries
  566. // Since NSBitmapImageRep doesn't have any sort of NSNullColorSpace
  567. // we must have at least one channel of non-alpha data. In order to
  568. // make our life easy, we use planar data which results in two
  569. // separate arrays. We don't need to touch the first because it
  570. // should never be used. The second is the 1-bit "alpha" data.
  571. NSBitmapImageRep *maskRep = [[[NSBitmapImageRep alloc]
  572. initWithBitmapDataPlanes:NULL pixelsWide:bmpWidth
  573. pixelsHigh:bmpHeight bitsPerSample:1
  574. samplesPerPixel:2 hasAlpha:YES isPlanar:YES
  575. colorSpaceName:NSCalibratedWhiteColorSpace
  576. bytesPerRow:dstRowLength bitsPerPixel:1] autorelease];
  577. wxCHECK(maskRep,false);
  578. // We need the source NSBitmapImageRep to detemine its pixel format
  579. NSBitmapImageRep *srcBitmapRep = const_cast<wxBitmap&>(bitmap).GetNSBitmapImageRep();
  580. wxCHECK_MSG(srcBitmapRep,false,wxT("Can't create mask for an uninitialized bitmap"));
  581. // Get a pointer to the destination data
  582. unsigned char *dstPlanes[5] = {NULL,NULL,NULL,NULL,NULL};
  583. [maskRep getBitmapDataPlanes:dstPlanes];
  584. unsigned char *dstData = dstPlanes[1];
  585. // The wxImage format (which we use whenever we imported from wxImage)
  586. if([srcBitmapRep bitsPerPixel]==24 && [srcBitmapRep bitsPerSample]==8 && [srcBitmapRep samplesPerPixel]==3 && [srcBitmapRep hasAlpha]==NO)
  587. {
  588. wxPixelData<wxBitmap,wxNativePixelFormat> pixelData(const_cast<wxBitmap&>(bitmap));
  589. wxCHECK_MSG(wxMask_CreateFromBitmapData(pixelData, colour, dstData),
  590. false, wxT("Unable to access raw data"));
  591. }
  592. // 32-bpp RGBx (x=throw away, no alpha)
  593. else if([srcBitmapRep bitsPerPixel]==32 && [srcBitmapRep bitsPerSample]==8 && [srcBitmapRep samplesPerPixel]==3 && [srcBitmapRep hasAlpha]==NO)
  594. {
  595. typedef wxPixelFormat<unsigned char,32,0,1,2> PixelFormat;
  596. wxPixelData<wxBitmap,PixelFormat> pixelData(const_cast<wxBitmap&>(bitmap));
  597. wxCHECK_MSG(wxMask_CreateFromBitmapData(pixelData, colour, dstData),
  598. false, wxT("Unable to access raw data"));
  599. }
  600. // 32-bpp RGBA
  601. else if([srcBitmapRep bitsPerPixel]==32 && [srcBitmapRep bitsPerSample]==8 && [srcBitmapRep samplesPerPixel]==4 && [srcBitmapRep hasAlpha]==YES)
  602. {
  603. wxPixelData<wxBitmap,wxAlphaPixelFormat> pixelData(const_cast<wxBitmap&>(bitmap));
  604. wxCHECK_MSG(wxMask_CreateFromBitmapData(pixelData, colour, dstData),
  605. false, wxT("Unable to access raw data"));
  606. }
  607. else if([srcBitmapRep bitsPerPixel]==8 && [srcBitmapRep bitsPerSample]==8 && [srcBitmapRep samplesPerPixel]==1 && [srcBitmapRep hasAlpha]==NO)
  608. // 8-bpp Grayscale, no alpha
  609. { // Force all RGB to access the same grayscale component
  610. typedef wxPixelFormat<unsigned char,8,0,0,0> PixelFormat;
  611. wxPixelData<wxBitmap,PixelFormat> pixelData(const_cast<wxBitmap&>(bitmap));
  612. wxCHECK_MSG(wxMask_CreateFromBitmapData(pixelData, colour, dstData),
  613. false, wxT("Unable to access raw data"));
  614. }
  615. else
  616. { wxCHECK_MSG(false,false,wxT("Unimplemented pixel format")); }
  617. // maskRep was autoreleased in case we had to exit quickly
  618. m_cocoaNSBitmapImageRep = wxGCSafeRetain(maskRep);
  619. return true;
  620. }