What is required for retina compatibility?

What is required for retina compatibility?

Lets say I am making a custom control, lets keep it simple, a button. What does this control need to be retina compatible?

Thanks.

  1. Must work in Cocoa
  2. Must have 2x graphics (if applicable)
  3. Must set NSHighResolutionCapable to True in app plist

See User Guide Book 4: Development, Chapter 2: Cross-Platform Development, Section 3.5: OS X Retina Displays

Thanks Paul, That has cleared it up

Is it a good idea only set NSHighResolutionCapable to True in app plist.
Will that mess up the GUI or will it look fine except the pictures?

I am wondering to do this first and do the picture work step by step.

The UI will look fine except for the pictures.

Great!
Thanks a lot.

For images I use RetinaKit. Makes it really easy :slight_smile:
http://ohanaware.com/retinakit/

If use the RetinaKit or NSImages, you can use PDF files as in app graphics.

If I set NSHighResolutionCapable to True the GUI looks fine.
But I still have problems with the pictures.

Let’s say I have a BevelButton and set the icon property to myPic (I did that at Xojo’s GUI)
It seems not enough to have also a myPic@2x.png inside my project.

Can someone tell me what code is needed to make it work on retina displays.
I really need to understand how it works before I use things like RetinaKit.

Thanks in advance.

You’ll need to swap the picture yourself when you detect a retina display. There is an example for this in User Guide Book 4: Development, Chapter 2: Cross-Platform Development, Section 3.5: OS X Features (Retina Displays).

And Xojo includes an example project: Examples/Platform-Specific/OS X/RetinaDisplay.

Ah I see…
I was hoping Apple would do the job for me.
So there is no need to name the retina picture with ‘@2x’ ! It can be anything else.
This is just the usual way. Am I right?
Thanks a lot.

The name can be anything since you are switching it yourself.

Thanks! Let’s get to work… :wink:

[quote=68998:@Michael Thaler]Ah I see…
I was hoping Apple would do the job for me.
So there is no need to name the retina picture with ‘@2x’ ! It can be anything else.
This is just the usual way. Am I right?
Thanks a lot.[/quote]
Well, if you use MacOSLib, MBS or the Retina Kit, then Apple will do it for you (it works for everything except Bevel Buttons and list boxes).
Basically all 3 of the above use the NSImage, which is how Apple handle Retina. The other advantage of using any one of the above toolkits is the use of PDF vector in your application. Smaller file sizes and scalable graphics :slight_smile:

Just to clarify
here is a snippet from the XOJO examples (Paint event of a Canvas)

[code]
If ScalingFactor > 1 Then
g.DrawPicture(Roulette2x, 0, 0, g.Width, g.Height, 0, 0, Roulette2x.Width, Roulette2x.Height)
Else
g.DrawPicture(Roulette1x, 0, 0)
End If

[code]

Retina or non-Retina… “G” is still always the same size (in this case 424x282)
Roulette1x is 424x283
Roulette2x is 849x566 (technically 2x size)

So to expand, the code above could be expressed like this … right?

[code]
If ScalingFactor > 1 Then
g.DrawPicture(Roulette2x, 0, 0, g.Width, g.Height, 0, 0, Roulette2x.Width, Roulette2x.Height)
Else
g.DrawPicture(Roulette1x, 0, 0, g.Width, g.Height, 0, 0, Roulette1x.Width, Roulette1x.Height)
End If

[code]

or even like this?

[code]
dim p as picture
If ScalingFactor > 1 Then
p=Roulette2x
Else
p=Roulette1x
End If
g.DrawPicture(p, 0, 0, g.Width, g.Height, 0, 0, p.Width, p.Height)

[code]

Meaning if everything is set up for Retina (modified plist? and determining scalefactor (as shown in example code))

Then DRAWPICTURE will handle the situation? (I assume by interpeting the first set of coordinates as PIXELS, and the 2nd set as POINTS?)

What about TEXT? and “drawn” graphics such as DrawLine etc.

I do not have a Retina device (yet), but would like to build as much infrastructure into my app as I can…

And for WINDOWS (xplat code)… use ScalingFactor=1 (ie… as if NON-Retina)

Don’t cache the scaling! Who ever started this bad habit, needs to be slapped!

I’ve recently been going through other peoples code removing this because their code doesn’t work correctly on a real Retina setup.

I’m away at the moment, so hopefully someone would be so kind as to post the correct declare that will obtain the scaling from the graphics context. If not I’ll post it myself when I can.

This is why I thought a white paper site would be a good idea… so we don’t have a bunch of 1/2 baked solutions that requires someone find them all, read them all, understand them all, and then realize what didn’t/doesn’t work.

Retina support should be transparent… as should sandboxing, code-signing etc… etc…

Not that any of my legit questions were answered… the point of my post was HOW DOES IT WORK… not best practices

You’re always going to get this, no matter what you do. Some people want the process of discovering for themselves. However I would agree that it cannot hurt to have information on how to do it correctly (within Xojo).

It will be once Xojo add native support for it.

Sorry I misunderstood, I thought they were statements.

Once the correct property is set in the plist, then yes Retina is enabled.

Consider the first set of co-ordinates as points and the second set as pixels.

g.drawpicture picture, x, y, w, h, 0, 0, picture.width, picture.height

then it doesn’t matter if you draw the low resolution or a higher resolution, as they’ll both be drawn in the correct rectangle.

No need to do anything, unless you’re drawing to an image and then to a canvas, in which case, don’t!

Windows has it’s own Retina system, it’s not as widely used as the Mac one and is very convoluted, one day I will invest the time into researching it and then supporting it within Windows apps (as we have some scheduled).

Following on from my previous post, if you want to handle drawing yourself, use the following code to choose which representation to display and do this at draw time, don’t cache this.

declare function CGContextConvertRectToDeviceSpace lib "Cocoa" ( context as integer, rect as CGRect) as CGRect Dim repRect as CGRect = CGContextConvertRectToDeviceSpace( g.Handle( g.HandleTypeCGContextRef ), CGRectMake( 0, 0, pic.width, pic.height) )
You’ll need a CGRect structure and a CGRectMake method. The returned rectangle will contain the ‘pixel dimensions’ of the passed rectangle. So from this you can determine which image you should be drawing at that time.

So I was close :slight_smile: … just backwards?

Would it make sense to create a custom DrawPicture routine encapsulating the above declare?

Expanding on something like this (based on Code you provided a few weeks ago :slight_smile: )

[code]
SUB myDRAWPICTURE(g as graphics, p as picture, x as integer, y as integer, w1 as integer = - 10000, h1 as integer = - 10000, sx as integer = 0, sy as integer = 0, w2 as integer = - 10000, h2 as integer = - 10000)

#If TargetMacOS Then
Dim Interpolation_Mode As Integer
// provided by Sam Rowlands
Const kCGInterpolationDefault = 0
Const kCGInterpolationNone = 1
Const kCGInterpolationLow = 2
Const kCGInterpolationMedium = 4
Const kCGInterpolationHigh = 3
//
Interpolation_Mode=kCGInterpolationNone
If w2>w1 Or h2>h1 Then Interpolation_Mode=kCGInterpolationMedium ’ reduced images
//
Declare Sub CGContextSetInterpolationQuality Lib “Cocoa” ( context As Integer, quality As Integer )
CGContextSetInterpolationQuality( g.handle( g.HandleTypeCGContextRef ), Interpolation_Mode )
//
#EndIf

g.drawpicture p,x,y,w1,h1,sx,sy,w2,h2
END SUB

can the declares be “stacked” without messing with each other?

If so, then we could have a single replacement to DrawPicture that would control Retina vs Non Retina, as well as Level of Interpolation (I have a program that needs to zoom in on a pic, but NOT alias the pixels (hence the code above))

Sure you can stack these declares.

The only thing to consider is that always drawing down, will have a memory overhead and slight speed degradation on non-retina systems. The memory issue becomes a moot point when loading both reps into memory and using the declare to choose which one to draw.

Using the Apple recommend way (via NSImage), you’d create a low resolution and a high resolution, the OS would then dynamically load/release the correct representation when required. This means that only the correct rep is loaded in memory and drawn.

The other thing I’ve seen recommend from Apple engineers is not to expect either 72 or 144 dpi. There may be other DPIs to handle in the future…