From 95aa8e40fd66ebeb14a63e916d3dc2058b46ed69 Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Tue, 28 Sep 2021 07:54:15 +0200 Subject: [PATCH] first part of OSX adaptations --- Makefile.in | 36 ++++++- build/bakefiles/files.bkl | 1 + build/cmake/files.cmake | 1 + build/files | 1 + include/wx/osx/cocoa/private.h | 2 + include/wx/osx/iphone/private.h | 2 + include/wx/private/bmpbndl.h | 18 ++++ src/common/bmpbndl.cpp | 47 ++++++++- src/osx/core/bmpbndl.mm | 180 ++++++++++++++++++++++++++++++++ 9 files changed, 282 insertions(+), 6 deletions(-) create mode 100644 src/osx/core/bmpbndl.mm diff --git a/Makefile.in b/Makefile.in index a2d91741d1..40586a21e1 100644 --- a/Makefile.in +++ b/Makefile.in @@ -13464,7 +13464,8 @@ COND_PLATFORM_MACOSX_1___OSX_LOWLEVEL_SRC_OBJECTS = \ monodll_hid.o \ monodll_printmac.o \ monodll_core_timer.o \ - monodll_utilsexc_cf.o + monodll_utilsexc_cf.o \ + monodll_core_bmpbndl.o @COND_PLATFORM_MACOSX_1@__OSX_LOWLEVEL_SRC_OBJECTS = $(COND_PLATFORM_MACOSX_1___OSX_LOWLEVEL_SRC_OBJECTS) @COND_PLATFORM_MACOSX_1@__PLATFORM_SRC_OBJECTS_0 = monolib_unix_apptraits.o @COND_PLATFORM_UNIX_1@__PLATFORM_SRC_OBJECTS_0 = monolib_unix_apptraits.o @@ -13601,7 +13602,8 @@ COND_PLATFORM_MACOSX_1___OSX_LOWLEVEL_SRC_OBJECTS_17 = \ monolib_hid.o \ monolib_printmac.o \ monolib_core_timer.o \ - monolib_utilsexc_cf.o + monolib_utilsexc_cf.o \ + monolib_core_bmpbndl.o @COND_PLATFORM_MACOSX_1@__OSX_LOWLEVEL_SRC_OBJECTS_17 = $(COND_PLATFORM_MACOSX_1___OSX_LOWLEVEL_SRC_OBJECTS_17) @COND_PLATFORM_MACOSX_1@__PLATFORM_SRC_OBJECTS_8 = coredll_unix_apptraits.o @COND_PLATFORM_UNIX_1@__PLATFORM_SRC_OBJECTS_8 = coredll_unix_apptraits.o @@ -13738,7 +13740,8 @@ COND_PLATFORM_MACOSX_1___OSX_LOWLEVEL_SRC_OBJECTS_1_1 = \ coredll_hid.o \ coredll_printmac.o \ coredll_core_timer.o \ - coredll_utilsexc_cf.o + coredll_utilsexc_cf.o \ + coredll_core_bmpbndl.o @COND_PLATFORM_MACOSX_1@__OSX_LOWLEVEL_SRC_OBJECTS_1_1 = $(COND_PLATFORM_MACOSX_1___OSX_LOWLEVEL_SRC_OBJECTS_1_1) @COND_PLATFORM_MACOSX_1@__PLATFORM_SRC_OBJECTS_9 = corelib_unix_apptraits.o @COND_PLATFORM_UNIX_1@__PLATFORM_SRC_OBJECTS_9 = corelib_unix_apptraits.o @@ -13875,7 +13878,8 @@ COND_PLATFORM_MACOSX_1___OSX_LOWLEVEL_SRC_OBJECTS_1_4 = \ corelib_hid.o \ corelib_printmac.o \ corelib_core_timer.o \ - corelib_utilsexc_cf.o + corelib_utilsexc_cf.o \ + corelib_core_bmpbndl.o @COND_PLATFORM_MACOSX_1@__OSX_LOWLEVEL_SRC_OBJECTS_1_4 = $(COND_PLATFORM_MACOSX_1___OSX_LOWLEVEL_SRC_OBJECTS_1_4) @COND_TOOLKIT_MSW@__webview_additional_include_wrl_p = \ @COND_TOOLKIT_MSW@ -I$(top_srcdir)/include/wx/msw/wrl @@ -19165,6 +19169,12 @@ monodll_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONODLL_ODEP) @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@monodll_utilsexc_cf.o: $(srcdir)/src/osx/core/utilsexc_cf.cpp $(MONODLL_ODEP) @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/osx/core/utilsexc_cf.cpp +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@monodll_core_bmpbndl.o: $(srcdir)/src/osx/core/bmpbndl.mm $(MONODLL_ODEP) +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_OBJCXXFLAGS) $(srcdir)/src/osx/core/bmpbndl.mm + +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@monodll_core_bmpbndl.o: $(srcdir)/src/osx/core/bmpbndl.mm $(MONODLL_ODEP) +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_OBJCXXFLAGS) $(srcdir)/src/osx/core/bmpbndl.mm + @COND_TOOLKIT_X11_USE_GUI_1@monodll_generic_timer.o: $(srcdir)/src/generic/timer.cpp $(MONODLL_ODEP) @COND_TOOLKIT_X11_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/generic/timer.cpp @@ -24460,6 +24470,12 @@ monolib_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONOLIB_ODEP) @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@monolib_utilsexc_cf.o: $(srcdir)/src/osx/core/utilsexc_cf.cpp $(MONOLIB_ODEP) @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/osx/core/utilsexc_cf.cpp +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@monolib_core_bmpbndl.o: $(srcdir)/src/osx/core/bmpbndl.mm $(MONOLIB_ODEP) +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_OBJCXXFLAGS) $(srcdir)/src/osx/core/bmpbndl.mm + +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@monolib_core_bmpbndl.o: $(srcdir)/src/osx/core/bmpbndl.mm $(MONOLIB_ODEP) +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_OBJCXXFLAGS) $(srcdir)/src/osx/core/bmpbndl.mm + @COND_TOOLKIT_X11_USE_GUI_1@monolib_generic_timer.o: $(srcdir)/src/generic/timer.cpp $(MONOLIB_ODEP) @COND_TOOLKIT_X11_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/generic/timer.cpp @@ -29860,6 +29876,12 @@ coredll_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(COREDLL_ODEP) @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@coredll_utilsexc_cf.o: $(srcdir)/src/osx/core/utilsexc_cf.cpp $(COREDLL_ODEP) @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/osx/core/utilsexc_cf.cpp +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@coredll_core_bmpbndl.o: $(srcdir)/src/osx/core/bmpbndl.mm $(COREDLL_ODEP) +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_OBJCXXFLAGS) $(srcdir)/src/osx/core/bmpbndl.mm + +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@coredll_core_bmpbndl.o: $(srcdir)/src/osx/core/bmpbndl.mm $(COREDLL_ODEP) +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_OBJCXXFLAGS) $(srcdir)/src/osx/core/bmpbndl.mm + @COND_TOOLKIT_X11_USE_GUI_1@coredll_generic_timer.o: $(srcdir)/src/generic/timer.cpp $(COREDLL_ODEP) @COND_TOOLKIT_X11_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/generic/timer.cpp @@ -34120,6 +34142,12 @@ corelib_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(CORELIB_ODEP) @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@corelib_utilsexc_cf.o: $(srcdir)/src/osx/core/utilsexc_cf.cpp $(CORELIB_ODEP) @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/osx/core/utilsexc_cf.cpp +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@corelib_core_bmpbndl.o: $(srcdir)/src/osx/core/bmpbndl.mm $(CORELIB_ODEP) +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_OBJCXXFLAGS) $(srcdir)/src/osx/core/bmpbndl.mm + +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@corelib_core_bmpbndl.o: $(srcdir)/src/osx/core/bmpbndl.mm $(CORELIB_ODEP) +@COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_IPHONE_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_OBJCXXFLAGS) $(srcdir)/src/osx/core/bmpbndl.mm + @COND_TOOLKIT_X11_USE_GUI_1@corelib_generic_timer.o: $(srcdir)/src/generic/timer.cpp $(CORELIB_ODEP) @COND_TOOLKIT_X11_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/generic/timer.cpp diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index 56d67f4d0b..4972cc72f4 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -2423,6 +2423,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/osx/core/printmac.cpp src/osx/core/timer.cpp src/osx/core/utilsexc_cf.cpp + src/osx/core/bmpbndl.mm diff --git a/build/cmake/files.cmake b/build/cmake/files.cmake index 3075665f09..032091d0de 100644 --- a/build/cmake/files.cmake +++ b/build/cmake/files.cmake @@ -2301,6 +2301,7 @@ set(OSX_LOWLEVEL_SRC src/osx/core/timer.cpp src/osx/core/utilsexc_cf.cpp #TODO: + src/osx/core/bmpbndl.mm ) set(OSX_LOWLEVEL_HDR diff --git a/build/files b/build/files index 299323c253..2112c0f6be 100644 --- a/build/files +++ b/build/files @@ -2279,6 +2279,7 @@ OSX_LOWLEVEL_SRC = src/osx/window_osx.cpp src/osx/core/bitmap.cpp + src/osx/core/bmpbndl.mm src/osx/core/colour.cpp src/osx/core/dcmemory.cpp src/osx/core/fontenum.cpp diff --git a/include/wx/osx/cocoa/private.h b/include/wx/osx/cocoa/private.h index 1538f6d5d0..4e29fb6291 100644 --- a/include/wx/osx/cocoa/private.h +++ b/include/wx/osx/cocoa/private.h @@ -23,6 +23,8 @@ // shared between Cocoa and Carbon // +#include "wx/bmpbndl.h" + // bring in theming types without pulling in the headers #if wxUSE_GUI diff --git a/include/wx/osx/iphone/private.h b/include/wx/osx/iphone/private.h index 42a4557879..0bb8939514 100644 --- a/include/wx/osx/iphone/private.h +++ b/include/wx/osx/iphone/private.h @@ -24,6 +24,8 @@ #if wxUSE_GUI +#include "wx/bmpbndl.h" + typedef CGRect WXRect; OSStatus WXDLLIMPEXP_CORE wxMacDrawCGImage( diff --git a/include/wx/private/bmpbndl.h b/include/wx/private/bmpbndl.h index fd17d82041..1d986a18cc 100644 --- a/include/wx/private/bmpbndl.h +++ b/include/wx/private/bmpbndl.h @@ -32,6 +32,24 @@ public: // Note that this function is non-const because it may generate the bitmap // on demand and cache it. virtual wxBitmap GetBitmap(const wxSize size) = 0; + +#ifdef __WXOSX__ + // returns the native representation of the bitmap bundle + virtual WXImage OSXGetImage() const { return NULL; } +#endif }; +#ifdef __WXOSX__ + +// this methods are wx-private, may change in the future + +WXImage WXDLLIMPEXP_CORE wxOSXGetImageFromBundle(const wxBitmapBundle& bundle); +wxBitmapBundle WXDLLIMPEXP_CORE wxOSXMakeBundleFromImage(WXImage image); +WXImage WXDLLIMPEXP_CORE wxOSXImageFromBitmap(const wxBitmap& bmp); +#if wxOSX_USE_COCOA +void WXDLLIMPEXP_CORE wxOSXAddBitmapToImage(WXImage image, const wxBitmap& bmp); +#endif + +#endif + #endif // _WX_PRIVATE_BMPBNDL_H_ diff --git a/src/common/bmpbndl.cpp b/src/common/bmpbndl.cpp index 709fca8009..f290617ee3 100644 --- a/src/common/bmpbndl.cpp +++ b/src/common/bmpbndl.cpp @@ -27,6 +27,10 @@ #include +#ifdef __WXOSX__ +#include "wx/osx/private.h" +#endif + // ---------------------------------------------------------------------------- // private helpers // ---------------------------------------------------------------------------- @@ -50,9 +54,24 @@ public: Init(&bitmap, 1); } + ~wxBitmapBundleImplSet() + { +#ifdef __WXOSX__ + if (m_nsImage) + wxMacCocoaRelease(m_nsImage); +#endif + } + virtual wxSize GetDefaultSize() const wxOVERRIDE; virtual wxBitmap GetBitmap(const wxSize size) wxOVERRIDE; +#ifdef __WXOSX__ + virtual WXImage OSXGetImage() const wxOVERRIDE; + +private: + mutable WXImage m_nsImage = NULL; +#endif + private: // Struct containing bitmap itself as well as a flag indicating whether we // generated it by rescaling the existing bitmap or not. @@ -196,6 +215,30 @@ wxBitmap wxBitmapBundleImplSet::GetBitmap(const wxSize size) return wxBitmap(); } +#ifdef __WXOSX__ +WXImage wxBitmapBundleImplSet::OSXGetImage() const +{ + if ( m_nsImage == NULL ) + { +#if wxOSX_USE_COCOA + m_nsImage = wxOSXImageFromBitmap(m_entries[0].bitmap); + const size_t n = m_entries.size(); + for ( size_t i = 1; i < n; ++i ) + { + const Entry& entry = m_entries[i]; + wxOSXAddBitmapToImage(m_nsImage, entry.bitmap); + } +#else + // TODO determine best bitmap for device scale factor, and use that + // with wxOSXImageFromBitmap as on iOS there is only one bitmap in a UIImage +#endif + if ( m_nsImage ) + wxMacCocoaRetain(m_nsImage); + } + return m_nsImage; +} +#endif + // ============================================================================ // wxBitmapBundle implementation // ============================================================================ @@ -252,7 +295,7 @@ wxBitmapBundle wxBitmapBundle::FromImpl(wxBitmapBundleImpl* impl) // MSW has its own, actually working, version, in MSW-specific code. -#ifndef __WXMSW__ +#if !defined( __WXMSW__ ) && !defined( __WXOSX__ ) /* static */ wxBitmapBundle wxBitmapBundle::FromResources(const wxString& WXUNUSED(name)) @@ -267,7 +310,7 @@ wxBitmapBundle wxBitmapBundle::FromResources(const wxString& WXUNUSED(name)) return wxBitmapBundle(); } -#endif // __WXMSW__ +#endif // !__WXMSW__ && !__WXOSX__ wxSize wxBitmapBundle::GetDefaultSize() const { diff --git a/src/osx/core/bmpbndl.mm b/src/osx/core/bmpbndl.mm new file mode 100644 index 0000000000..582d171b82 --- /dev/null +++ b/src/osx/core/bmpbndl.mm @@ -0,0 +1,180 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/osx/core/bmpbndl.mm +// Purpose: OSX-specific part of wxBitmapBundle class. +// Author: Vadim Zeitlin and Stefan Csomor +// Created: 2021-09-22 +// Copyright: (c) 2021 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// for compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP +#endif // WX_PRECOMP + +#include "wx/bmpbndl.h" + +#include "wx/private/bmpbndl.h" + +#include "wx/osx/private.h" + +#include + +// ---------------------------------------------------------------------------- +// private helpers +// ---------------------------------------------------------------------------- + +namespace +{ +// Bundle implementation using PNG bitmaps from Windows resources. +class wxOSXImageBundleImpl : public wxBitmapBundleImpl +{ +public: + // Ctor takes the vector containing all the existing resources starting + // with the given name and the valid bitmap corresponding to the base name + // resource itself. + wxOSXImageBundleImpl(WXImage image); + ~wxOSXImageBundleImpl(); + + virtual wxSize GetDefaultSize() const wxOVERRIDE; + virtual wxBitmap GetBitmap(const wxSize size) wxOVERRIDE; + + virtual WXImage OSXGetImage() const wxOVERRIDE; + +private: + WXImage m_nsImage; +}; + +} // anonymouse namespace + +// ============================================================================ +// wxOSXImageBundleImpl implementation +// ============================================================================ + +wxOSXImageBundleImpl::wxOSXImageBundleImpl(WXImage image) +{ + m_nsImage = (WXImage) wxMacCocoaRetain(image); +} + +wxOSXImageBundleImpl::~wxOSXImageBundleImpl() +{ + wxMacCocoaRelease(m_nsImage); +} + +wxSize wxOSXImageBundleImpl::GetDefaultSize() const +{ + CGSize sz = wxOSXGetImageSize(m_nsImage); + return wxSize(sz.width, sz.height); +} + +wxBitmap wxOSXImageBundleImpl::GetBitmap(const wxSize size) +{ + return wxBitmap(); +} + +WXImage wxOSXImageBundleImpl::OSXGetImage() const +{ + return m_nsImage; +} + +wxBitmapBundle wxOSXMakeBundleFromImage( WXImage img) +{ + return wxBitmapBundle::FromImpl( new wxOSXImageBundleImpl(img) ); +} + +// ============================================================================ +// wxOSXImageBundleImpl implementation +// ============================================================================ + +WXImage wxOSXImageFromBitmap( const wxBitmap& bmp) +{ + WXImage image; +#if wxOSX_USE_COCOA + double scale = bmp.GetScaleFactor(); + NSSize sz = NSMakeSize( bmp.GetWidth()*scale, bmp.GetHeight()*scale); + image = [[NSImage alloc] initWithSize:sz]; + wxOSXAddBitmapToImage(image, bmp); +#else + wxCFRef cgimage = bmp.CreateCGImage(); + image = [[UIImage alloc] initWithCGImage:cgimage scale:bmp.GetScaleFactor() orientation:UIImageOrientationUp]; +#endif + [image autorelease]; + return image; +} + +#if wxOSX_USE_COCOA +void wxOSXAddBitmapToImage( WXImage image, const wxBitmap& bmp) +{ + wxCFRef cgimage = bmp.CreateCGImage(); + NSImageRep* nsrep = [[NSBitmapImageRep alloc] initWithCGImage:cgimage]; + [image addRepresentation:nsrep]; + [nsrep release]; +} +#endif + +wxBitmapBundle wxBitmapBundle::FromResources(const wxString& name) +{ + wxVector resources; + + wxString ext = "png"; // TODO adapt as soon as we get res param + wxCFStringRef restype(ext); + + for ( int dpiFactor = 1 ; dpiFactor <= 2 ; ++dpiFactor) + { + wxString filename; + if ( dpiFactor == 1 ) + filename = name; + else + filename = wxString::Format("%s@%dx", name, dpiFactor); + + wxCFStringRef resname(filename); + wxCFRef imageURL(CFBundleCopyResourceURL(CFBundleGetMainBundle(), resname, restype, NULL)); + if ( !imageURL.get() && dpiFactor != 1 ) + { + // try alternate naming scheme + filename = wxString::Format("%s_%dx", name, dpiFactor); + resname = wxCFStringRef(filename); + imageURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), resname, restype, NULL); + } + if ( imageURL.get() ) + { + // Create the data provider object + wxCFRef provider(CGDataProviderCreateWithURL (imageURL) ); + CGImageRef image = NULL; + + if ( ext == "jpeg" ) + image = CGImageCreateWithJPEGDataProvider (provider, NULL, true, + kCGRenderingIntentDefault); + else if ( ext == "png" ) + image = CGImageCreateWithPNGDataProvider (provider, NULL, true, + kCGRenderingIntentDefault); + if ( image != NULL ) + { + wxBitmap bmp(image, dpiFactor); + CGImageRelease(image); + resources.push_back(bmp); + } + } + } + + return wxBitmapBundle::FromBitmaps(resources); +} + +WXImage wxOSXGetImageFromBundle(const wxBitmapBundle& bundle) +{ + WXImage image = bundle.GetImpl()->OSXGetImage(); + + if (image == 0) + image = bundle.GetBitmap(bundle.GetDefaultSize()).OSXGetImage(); + + return image; +}