This chapter explains the basics of resolution independence: what it is and how it works.
Historically, image dimensions were described in pixels, such as a 100 x 20 pixel button. The user space (that is, the idealized coordinate system the application draws into) was essentially the same as the device space (the coordinate system corresponding to the pixels of an output device). For example, when using Carbon QuickDraw, applications drew into the user space assuming that one QuickDraw unit corresponded to one pixel onscreen.
Quartz introduced an abstract coordinate system, which had no ties to real-world display pixels. However, you could assume that these Quartz units (typically called points) had a scale of about 72 units per inch. Onscreen, one Quartz point still mapped to one pixel. Doing so was reasonable, as physical display resolutions were about 72 dots (or pixels) per inch (dpi) and having a one-to-one correspondence between drawing units and onscreen pixels resulted in a reasonably sized image. Unfortunately, with the increasing pixel density of today's LCD displays, this fixed resolution is becoming an obstacle. As the pixel density increases, the comparative size of an image described in pixels grows smaller and smaller. On a 144 dpi screen, a 200 x 200 image is one quarter the size of a comparable image on a 72 dpi screen.
Resolution independence allows greater flexibility with high-density displays by allowing a Quartz point to map to any number of pixels (or fractions thereof). You can no longer assume a 1:1 correspondence between a Quartz point and an onscreen pixel as shown in Figure 1-1.
Note: Resolution independence for display devices is analogous to the scaling that occurs when printing; whether printing on a 300 dpi printer or a 1200 dpi printer, a line 72 points long always appears as roughly one inch long on paper (assuming standard size output).
Resolution independence makes it possible to choose between seeing more detail (more pixels per unit point) versus having more screen real estate (fewer pixels per unit point, but more points onscreen). A new parameter, called the scale factor, is required to govern the ratio between an onscreen pixel and a Quartz unit.
Currently, a scale factor of 1.0 corresponds to 72 dpi. If a display had a pixel density of 144 dpi, software would have to scale an image by a factor of 2.0 in order for it to appear the same size as on a 72 dpi display. In a similar fashion, say you had two displays of the same physical size, but one has a 1024 x 768 pixel resolution and the other 1536 x 1152 pixels. To make the higher-density display show the same amount of screen real estate, you would have to apply a scale factor of 1536/1024 = 1.5 to its user interface. Given that scaling, the high-density screen would look the same from a distance, but a close-range view would display more detail as shown in Figure 1-2.
The scale factor applies only to onscreen displays, not printing. In actuality, printers already use a form of scaling when rendering a page. For example, you can print a document to both a 300 dpi and 1200 dpi printer and the output is the same size; the output from the 1200 dpi printer is just crisper and shows more detail.
The default scale factor is 1.0 (no scaling). You can test other scale factors on a system-wide basis using the Quartz Debug application, or on a per-application basis using the defaults database.
You can use the Quartz Debug application to change the scale factor on a system-wide basis. Quartz Debug is available in the Developer installation at /Developer/Applications/Performance Tools/
. To change the scale factor globally:
Launch the Quartz Debug application.
From the Tools menu, choose Show User Interface Resolution. A User Interface Resolution window appears.
Select the new scale factor by moving the slider.
The scale factor you select does not affect currently running applications, but any applications launched after changing the scale factor are resized accordingly.
To run a specific application with a scale factor that’s different from the global scale factor, you can add an AppleDisplayScaleFactor
entry for the application to the defaults database. For example, to run the Mail application with a 1.25 scale factor:
Determine the bundle identifier. Bundle identifiers are defined in the Info.plist
dictionary inside the application bundle. The bundle identifier for Mail is com.apple.mail
.
Quit Mail, launch the Terminal application, and execute this command:
defaults write com.apple.mail AppleDisplayScaleFactor 1.25 |
Launch Mail and confirm that its user interface is now scaled appropriately.
To delete the scale factor entry for Mail, execute this command:
defaults delete com.apple.mail AppleDisplayScaleFactor |
Given that the scale factor is adjustable, application user interfaces now have to adjust their size accordingly. For example, a user interface displayed on a 144 dpi display would have to have its dimensions doubled in order to appear the same size as it did on a 72 dpi display. In theory, an unscaled interface might still be usable, but many of its features would appear very small (such as buttons, checkboxes, and so on). Any application that makes assumptions about how Quartz units relate to screen pixels definitely needs to scale its user interface accordingly.
The amount of work needed to scale the user interface depends on the application code base. Resolution independence has two adoption paths: using framework-scaled mode and using magnified mode.
Framework-scaled mode means that the application framework (Cocoa or Carbon) automatically adjusts the drawing size depending on the scale factor. The size of the window buffer is increased to accommodate the actual number of pixels to be drawn to the screen, as shown in Figure 1-3.
Note: The application user space in Figure 1-3 is drawn the same size as the window buffer and the display because the same amount of window area is being covered, even though the units that describe the space are different.
Application frameworks such as Carbon and Cocoa scale all standard user interface elements (such as buttons, menus, and the window title bar) to the correct size. In addition, the frameworks add a scaling transform to a window's Quartz context, so that any content drawn using Quartz or the Application Kit is scaled automatically.
Cocoa applications automatically use framework-scaled mode, and in most cases you don't have to do any work to support resolution independence. However, if your Cocoa code uses any QuickDraw calls, you need to replace them with their Quartz equivalents.
Carbon applications can use framework-scaled mode if they use compositing windows that contain HIView-based controls and they draw using Quartz. Windows also need to have the framework-scaled attribute set, either by selecting the attribute in the Inspector window in Interface Builder, or by specifying kWindowFrameworkScaledAttribute
at window creation time.
Magnified mode is the default compatibility mode for providing basic scaling support in Carbon applications that can’t use framework-scaled mode. The window server applies the current scale factor to the window buffer to create a magnified view of the window, as shown in Figure 1-4. That is, the window is simply enlarged to scale, with no additional detail, and may look slightly blurry as a result.
Because of the loss of detail, you should rely on magnified mode only until you make the necessary changes to support framework scaling in your application. You should adopt compositing windows, use HIView-based controls, and draw using Quartz.
In this document, the coordinate system used to draw in application windows is referred to as user space. This name is akin to the term Quartz uses. In Quartz, user space is often contrasted with device space, which represents the coordinate system used by a display device (a monitor, printer, and so on).
When in resolution-independent mode, all onscreen positions and bounds are automatically translated to their proper equivalents in user space. The coordinate system used depends on the scale mode.
When drawing with Quartz in framework-scaled mode, user space is the same coordinate system used by Quartz. Some documentation refers to this coordinate system as being 72 points per inch, but you cannot assume a 1:1 correspondence between Quartz units and pixels. All coordinates are view-relative, as is standard for Cocoa views and HIViews.
When Carbon applications use older QuickDraw-based or noncompositing windows (that is, in magnified mode), user space is the old-style pseudo-72 dpi coordinate space, in which one unit in user space is assumed to correspond to one pixel. To ensure that older Carbon functions still work properly, all window positions, bounds, and so on, are presented to the application in this coordinate system, as are global values such as mouse click positions, or Carbon event parameters that assume global coordinates.
A single process can handle multiple scale modes on a window-by-window basis. For example, a Carbon application might contain a magnified Carbon window, a framework-scaled Carbon window, and a framework-scaled Cocoa window. It’s important to note that Cocoa applications do not support magnified Carbon windows well. If you’re using Carbon windows in a Cocoa application, the Carbon windows should be framework-scaled.
Many of the methods and functions you need to use for correct coordinate conversion in a resolution-independent environment are available in earlier versions of Mac OS X. With framework scaling in Mac OS X v10.5, it is now important to make sure you are using these facilities correctly and consistently.
Last updated: 2007-05-04