Page 1 of 1

Retina Support for Mac

Posted: Thu Apr 26, 2018 12:16 am
by BeerSmith
I've researched this but really don't understand how to incorporate Retina support for various size icons into my program. Currently my icons are fuzzy when I go to a Retina display on Mac.

Currently at startup I load all of my icons as images from png files using wxImage::LoadFile() and then convert those to bitmaps which I use throughout the program for lists, toolbars, etc... I have @2x versions of these png files as well in the same locations, but they don't do anything.

So is there some magic trick or flag to get the wxImage or wxBitmap to load the retina @2x images with the regular png images so they will display clearly on a Retina display?

Thanks,
Brad

Re: Retina Support for Mac

Posted: Thu Apr 26, 2018 9:42 am
by eranon
Hello,

Do you have the magic declaration "<key>NSPrincipalClass</key><string>NSApplication</string>" in your Info.plist?

Here is the way I load mine in one of my apps running under both Windows and Mac below (shopifight_icon being an embedded array built through wxInclude from a PNG file). Also, notice that, strictly, wxIconBundle should contain multiple icon copies in different sizes to never stretch and introduce any blur.

Code: Select all

    // App icon
    wxIconBundle iconset;
    wxIcon icon;
    icon.CopyFromBitmap(wxGetBitmapFromMemory(shopifight_icon));
    iconset.AddIcon(icon);
    SetIcons(iconset);
with:

Code: Select all

#define wxGetBitmapFromMemory(name) _wxGetBitmapFromMemory(name, sizeof(name))
inline wxBitmap _wxGetBitmapFromMemory(const unsigned char *data, int length)
{
    wxMemoryInputStream is(data, length);
    return wxBitmap(wxImage(is, wxBITMAP_TYPE_ANY, -1), -1);
}
EDIT: And (may count), what version of wxWidgets do you use here?
EDIT #2: Well, not very clear mind today:)... Also (and I hope finally) in some circumstances (but really don't remember exactly which; certainly to use for display in the Finder, desktop, info box, etc., outside of the app itself), OS X/ macOS needs an icon through its how convention: ie. a .icns file. So, you have to place one in the app bundle (Resource) and declare it in Info.plist like this below. This was my last EDIT, promise ^^

Code: Select all

<key>CFBundleIconFile</key><string>alify.icns</string>

Re: Retina Support for Mac

Posted: Thu Apr 26, 2018 2:39 pm
by ONEEYEMAN
eranon,
All this should be done for you in Xcode, right?

Thank you.

Re: Retina Support for Mac

Posted: Sat Apr 28, 2018 12:02 pm
by eranon
Hello, Sorry for the delay, a little busy these days. I guess you can manage Info.plist and app bundle in Xcode, but I can't tell you how... I don't use Xcode on my part (I'm using Code::Blocks in both Windows and OS X). So, I edit Info.plist myself and I create the app bundle on post-build stage through a shell script.

Anyway, with or without Xcode, if you want to check if you have the right Info.plist and a .icns icon in the right place, you can open the generated app bundle in the Finder and see what it contains.

And for the part about code, it's the same whatever IDE you use :wink:

Re: Retina Support for Mac

Posted: Fri Apr 19, 2019 7:53 pm
by chrism238
Hello; in my macOS application I load two PNG images :

- one is 16x16 pixels, stored in a file named, say, car.png
- the other is "the same" image but at 32x32 pixels, stored in a file named [email protected] (a "retina" version)

The code

Code: Select all

bm0 = wxBitmap("..../car.png", wxBITMAP_TYPE_PNG);
printf("%i x %i\n", bm0.GetWidth(), bm0.GetHeight() );
correctly prints 16x16, and similar code for

Code: Select all

bm1 = wxBitmap("..../vehicle.png", ....
correctly prints 32x32.

Now, I wish to centre both images around two points (px0,py) and (px1,py) so that, despite the images having different resolutions, they should both appear on the same line at py. Of course,

Code: Select all

dc.DrawBitmap(bm0, x - bm.GetWidth() / 2, y - bm.GetHeight() / 2);
works for the 16x16 image, but not the 32x32 image because it will be rendered differently.

Given a wxBitmap, or a wxImage or the underlying raw data, how can I determine the size at which it will be rendered, so that I can centre it?

Thank you.

Re: Retina Support for Mac

Posted: Fri Apr 19, 2019 9:27 pm
by doublemax
Try double wxBitmap::GetScaleFactor().

You'll probably need the latest wxWidgets version from GIT for this.
(Check <wxdir>/include/wx/bitmap.h to see if the method exists).

Re: Retina Support for Mac

Posted: Fri Apr 19, 2019 11:38 pm
by chrism238
doublemax wrote: Fri Apr 19, 2019 9:27 pm Try double wxBitmap::GetScaleFactor().

You'll probably need the latest wxWidgets version from GIT for this.
(Check <wxdir>/include/wx/bitmap.h to see if the method exists).
Thanks very much, that's solved it!
I'm using v3.1.1 and the indicated header file "reveals" lots of useful functions:

Code: Select all

    // support for scaled bitmaps
    virtual double GetScaleFactor()  const { return 1.0; }
    virtual double GetScaledWidth()  const { return GetWidth() / GetScaleFactor(); }
    virtual double GetScaledHeight() const { return GetHeight() / GetScaleFactor(); }
    virtual wxSize GetScaledSize() const
        { return wxSize(wxRound(GetScaledWidth()), wxRound(GetScaledHeight())); }