objective-ccocoaresolutionppi

Understanding points and the user space in Cocoa Drawing as they interact with screen resolution


Cocoa drawing sizes (widths & heights) are specified in points which are defined as follows in the OS X Cocoa Drawing Guide documentation:

"A single point is equivalent to 1/72 of an inch"

I understand from this that a point is a physical distance. So if my screen is 20 inches wide (for example) I would have 20 x 72 = 1440 points of horizontal width in points to work with. In other words, a point is independent of the resolution of the device.

This does not seem to be so...

A simple cocoa application using window width as a test shows that: 1) when my resolution is set to 1680x1050 it will take a width of 1680 points to span the width of the screen 2) similarly, if I change my resolution to 2560x1440 it will take a window width of 2560 points to span the width of the screen

Also confusing (in a contradictory way) is the statement made in the High Resolution Guidelines Apple Document that:

Each point in user space is backed by four pixels

The above tests seem to indicate that I have a user space of 1680x1050 when my display resolution is set to 1680x1050. If there are 4 pixels per user point then this would point to an effective "real" resolution of 2 times (1680x1050) = 3360x2100 which is more than the native resolution my 13 inch retina macbook pro of 2560x1600.


Solution

  • Points are an abstract, virtual coordinate system. The intent is that you usually design and write drawing code to work in points and that will be roughly consistent to human vision, compensating for different physical display pixel densities and the usual distance between the display and the user's eyes.

    Points do not have a reliable relationship to either physical distance units (inches, centimeters, etc.) or physical display pixels.

    For screen displays, there are at least three different measurements. For example, the screen of a Retina MacBook Pro has 2880x1800 physical pixels. In the default mode, that's mapped to 1440x900 points, so each point is a 2x2-pixel square. That's why a window on such a system has the same visual size as the same window on a non-Retina MacBook Pro with a screen with 1440x900 physical pixels mapped to 1440x900 points. The window is measured in points and so takes up the same portion of the screen real estate. However, on the Retina display, there are more pixels allowing for finer detail.

    However, there is another layer of complexity possible. You can configure that Retina system to display more content on the screen at the cost of some of the detail. You can select a display mode of 1920x1200 points. In that mode, the rendering is done to a backbuffer of 3840x2400 pixels. That allows for rendering at a higher level of detail but keeps the math simple; points are still mapped to 2x2-pixel squares. (This simple math also avoids problems with seams when drawing abutting bitmap images.) But 3840x2400 is greater than the number of physical pixels in the display hardware. So, that backbuffer is scaled down when actually drawn on the screen to the physical 2880x1800 pixels. This loses some of the higher detail from the backbuffer, but the results are still finer-detailed than either a physical 1920x1200 screen or scaling up a 1920x1200 rendering to the physical 2880x1800 screen.

    So, for this configuration:
    Screen size in points: 1920x1200
    Backbuffer in in-memory pixels: 3840x2400
    Physical pixels in display hardware: 2880x1800

    Other configurations are, of course, possible:

    Screen size in points: 2880x1800
    Backbuffer in pixels: 2880x1800
    Physical pixels: 2880x1800
    Everything will be teeny-tiny but you'll be able to fit a lot of stuff (e.g. many lines of text) on the screen.

    Screen size in points: 1280x800
    Backbuffer in pixels: 2560x1600
    Physical pixels: 2880x1800
    This will actually make everything (text, buttons, etc.) appear larger since there are fewer points mapped to the same physical pixels. Each point will be physically larger. Note, though, that each point still maps to a 2x2-pixel square in the backbuffer. As before, the backbuffer is scaled by the hardware to the physical display. This time it's scaled up slightly rather than down. (This scaling is the same thing as happens on a non-Retina LCD display when you select a mode with fewer pixels than the physical display. Obviously, an LCD can't change the number of physical pixels it has, so the different resolution is accomplished by scaling a backbuffer.)

    Etc.