Skip to content

Commit

Permalink
Merge remote-tracking branch 'MaartenBent/bitmap_cursor_osx'
Browse files Browse the repository at this point in the history
Add wxBitmap(const wxCursor &cursor) constructor to wxOSX.

See wxWidgets#2314
  • Loading branch information
vadz committed Apr 11, 2021
2 parents cace392 + 3a27830 commit b671d23
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 14 deletions.
5 changes: 5 additions & 0 deletions include/wx/osx/bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ class WXDLLIMPEXP_CORE wxBitmap: public wxBitmapBase
// Convert from wxIcon
wxBitmap(const wxIcon& icon) { CopyFromIcon(icon); }

#if wxOSX_USE_COCOA
// Convert from wxCursor
wxBitmap(const wxCursor &cursor);
#endif

virtual ~wxBitmap() {}

wxImage ConvertToImage() const wxOVERRIDE;
Expand Down
1 change: 1 addition & 0 deletions include/wx/osx/cocoa/private.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ void WXDLLIMPEXP_CORE wxOSXSetImageSize(WX_NSImage image, CGFloat width, CGFloat
wxBitmap WXDLLIMPEXP_CORE wxOSXCreateSystemBitmap(const wxString& id, const wxString &client, const wxSize& size);
WXWindow WXDLLIMPEXP_CORE wxOSXGetMainWindow();
WXWindow WXDLLIMPEXP_CORE wxOSXGetKeyWindow();
WXImage WXDLLIMPEXP_CORE wxOSXGetNSImageFromNSCursor(const WXHCURSOR cursor);

class WXDLLIMPEXP_FWD_CORE wxDialog;

Expand Down
3 changes: 0 additions & 3 deletions interface/wx/bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,9 +359,6 @@ class wxBitmap : public wxGDIObject
This can be useful to display a cursor as it cannot be drawn directly
on a window.
This constructor only exists in wxMSW and wxGTK (where it is
implemented for GTK+ 2.8 or later) only.
@param cursor A valid wxCursor.
@since 3.1.0
Expand Down
5 changes: 5 additions & 0 deletions src/osx/carbon/utilscocoa.mm
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,11 @@ WX_NSCursor wxMacCocoaCreateStockCursor( int cursor_type )
return cursor;
}

WXImage WXDLLIMPEXP_CORE wxOSXGetNSImageFromNSCursor(const WXHCURSOR cursor)
{
return [(NSCursor *)cursor image];
}

// C-based style wrapper routines around NSCursor
WX_NSCursor wxMacCocoaCreateCursorFromCGImage( CGImageRef cgImageRef, float hotSpotX, float hotSpotY )
{
Expand Down
7 changes: 7 additions & 0 deletions src/osx/core/bitmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,13 @@ wxBitmap::wxBitmap(WXImage image)
(void)Create(image);
}

#if wxOSX_USE_COCOA
wxBitmap::wxBitmap(const wxCursor &cursor)
{
m_refData = new wxBitmapRefData( wxOSXGetNSImageFromNSCursor( cursor.GetHCURSOR() ) );
}
#endif

bool wxBitmap::Create(WXImage image)
{
UnRef();
Expand Down
78 changes: 67 additions & 11 deletions tests/image/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#endif // WX_PRECOMP

#include "wx/anidecod.h" // wxImageArray
#include "wx/bitmap.h"
#include "wx/palette.h"
#include "wx/url.h"
#include "wx/log.h"
Expand All @@ -31,6 +32,18 @@

#include "testimage.h"


#define CHECK_EQUAL_COLOUR_RGB(c1, c2) \
CHECK( (int)c1.Red() == (int)c2.Red() ); \
CHECK( (int)c1.Green() == (int)c2.Green() ); \
CHECK( (int)c1.Blue() == (int)c2.Blue() )

#define CHECK_EQUAL_COLOUR_RGBA(c1, c2) \
CHECK( (int)c1.Red() == (int)c2.Red() ); \
CHECK( (int)c1.Green() == (int)c2.Green() ); \
CHECK( (int)c1.Blue() == (int)c2.Blue() ); \
CHECK( (int)c1.Alpha() == (int)c2.Alpha() )

struct testData {
const char* file;
wxBitmapType type;
Expand Down Expand Up @@ -82,6 +95,7 @@ class ImageTestCase : public CppUnit::TestCase
CPPUNIT_TEST( DibPadding );
CPPUNIT_TEST( BMPFlippingAndRLECompression );
CPPUNIT_TEST( ScaleCompare );
CPPUNIT_TEST( CreateBitmapFromCursor );
CPPUNIT_TEST_SUITE_END();

void LoadFromSocketStream();
Expand All @@ -102,6 +116,7 @@ class ImageTestCase : public CppUnit::TestCase
void DibPadding();
void BMPFlippingAndRLECompression();
void ScaleCompare();
void CreateBitmapFromCursor();

wxDECLARE_NO_COPY_CLASS(ImageTestCase);
};
Expand Down Expand Up @@ -1451,6 +1466,58 @@ void ImageTestCase::ScaleCompare()
"image/cross_nearest_neighb_256x256.png");
}

void ImageTestCase::CreateBitmapFromCursor()
{
#if !defined __WXOSX_IPHONE__ && !defined __WXDFB__ && !defined __WXMOTIF__ && !defined __WXX11__

wxImage image("image/wx.png");
wxCursor cursor(image);
wxBitmap bitmap(cursor);

#if defined(__WXGTK__)
// cursor to bitmap could fail depending on windowing system and cursor (gdk-cursor-get-image)
if ( !bitmap.IsOk() )
return;
#endif

wxImage result = bitmap.ConvertToImage();

// on Windows the cursor is always scaled to 32x32px (96 DPI)
// on macOS the resulting bitmap size depends on the DPI
if ( image.GetSize() == result.GetSize() )
{
CHECK_THAT(image, RGBASimilarTo(result, 2));
}
else
{
wxVector<wxPoint> coords;
coords.push_back(wxPoint(14, 10)); // blue square
coords.push_back(wxPoint(8, 22)); // red square
coords.push_back(wxPoint(26, 18)); // yellow square
coords.push_back(wxPoint(25, 5)); // empty / tranparent

for ( size_t i = 0; i < coords.size(); ++i )
{
wxPoint const& p1 = coords[i];
wxPoint p2 = wxPoint(p1.x * (result.GetWidth() / (double)image.GetWidth()), p1.y * (result.GetHeight() / (double)image.GetHeight()));

#if defined(__WXMSW__)
// when the cursor / result image is larger than the source image, the original image is centered in the result image
if ( result.GetWidth() > image.GetWidth() )
p2.x = (result.GetWidth() / 2) + (p1.x - (image.GetWidth() / 2));
if ( result.GetHeight() > image.GetHeight() )
p2.y = (result.GetHeight() / 2) + (p1.y - (image.GetHeight() / 2));
#endif

wxColour cSrc(image.GetRed(p1.x, p1.y), image.GetGreen(p1.x, p1.y), image.GetBlue(p1.x, p1.y), image.GetAlpha(p1.x, p1.y));
wxColour cRes(result.GetRed(p2.x, p2.y), result.GetGreen(p2.x, p2.y), result.GetBlue(p2.x, p2.y), result.GetAlpha(p2.x, p2.y));

CHECK_EQUAL_COLOUR_RGBA(cRes, cSrc);
}
}
#endif
}

#endif //wxUSE_IMAGE

TEST_CASE("wxImage::Paste", "[image][paste]")
Expand Down Expand Up @@ -1970,17 +2037,6 @@ TEST_CASE("wxImage::Clipboard", "[image][clipboard]")
#endif // wxUSE_CLIPBOARD && wxUSE_DATAOBJ
}

#define CHECK_EQUAL_COLOUR_RGB(c1, c2) \
CHECK( (int)c1.Red() == (int)c2.Red() ); \
CHECK( (int)c1.Green() == (int)c2.Green() ); \
CHECK( (int)c1.Blue() == (int)c2.Blue() )

#define CHECK_EQUAL_COLOUR_RGBA(c1, c2) \
CHECK( (int)c1.Red() == (int)c2.Red() ); \
CHECK( (int)c1.Green() == (int)c2.Green() ); \
CHECK( (int)c1.Blue() == (int)c2.Blue() ); \
CHECK( (int)c1.Alpha() == (int)c2.Alpha() )

TEST_CASE("wxImage::InitAlpha", "[image][initalpha]")
{
const wxColour maskCol(*wxRED);
Expand Down
5 changes: 5 additions & 0 deletions tests/testimage.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ inline ImageRGBMatcher RGBSimilarTo(const wxImage& image, int tolerance)
return ImageRGBMatcher(image, tolerance, false);
}

inline ImageRGBMatcher RGBASimilarTo(const wxImage& image, int tolerance)
{
return ImageRGBMatcher(image, tolerance, true);
}

class ImageAlphaMatcher : public Catch::MatcherBase<wxImage>
{
public:
Expand Down

0 comments on commit b671d23

Please sign in to comment.