Given any screen resolution, is there a way that I can figure out the amount of points in an inch? For instance, if I wanted to create an NSView
that was 8.5 inches by 11 inches (like a sheet of a paper), is there an algorithm that will allow me to obtain the correct point values for the frame
across many different types of Macs and screen resolutions?
It's not straightforward. I'm not sure there's a good way. I can provide an approach, but I haven't confirmed that this works reliably:
First, you can use CGDisplayScreenSize()
to get the screen's physical size in millimeters. You can obtain the CGDirectDisplayID
for a screen from NSScreen
, which you can, in turn, get from the window. Obtain the screen's deviceDescription
and get the value for the "NSScreenNumber"
key. That may need to be cast to CGDirectDisplayID
.
The problem from there is that the display mode may not fill the screen. It could be letterboxed or pillarboxed. Or, it might be stretched. This should be fairly uncommon these days, but still possible. You can obtain the display mode using CGDisplayCopyDisplayMode()
. To determine if it's stretched, you can examine its ioFlags
to see if they contain the bitmask kDisplayModeStretchedFlag
(declared in IOKit).
If it's stretched, the screen's frame
will have to be mapped to its size in millimeters separately for the X and Y axes. You assume the screen's frame.width
(in points) maps to the full physical width, and similarly for the height.
If the mode is not stretched, you'll have to check the aspect ratio of the frame and the screen physical size to see if it's letter- or pillarboxed. If the aspect ratios are very close, then it's presumably not. That case is similar to the stretched case, but the width and height mappings should be equivalent.
If the aspect ratios differ significantly, then you compare them. If the screen's physical aspect ratio is larger than the frame's, then the screen is physically wider than the mode is using (pillarboxed). So, you compute the mapping from points to millimeters from the two heights. If the physical aspect ratio is smaller than the logical one, then the mode is letterboxed and you use the widths to compute the mapping.