Cocoa and Quartz use the same base coordinate system model. Before you can draw effectively, you need to understand this coordinate space and how it affects your drawing commands. It also helps to know the ways in which you can modify the coordinate space to simplify your drawing code.
Local Coordinate Systems
Points Versus Pixels
Cocoa uses a Cartesian coordinate system as its basic model for specifying coordinates. The origin in this system is located in the lower-left corner of the current drawing space, with positive values extending along the axes up and to the right of the origin point. The root origin for the entire system is located in the lower-left corner of the user’s main screen.
If you were forced to draw all your content relative to the origin of the screen, your code would be quite complex, so Cocoa simplifies things by changing the origin point based on the current context. Before calling your drawing code, Cocoa adjusts the origin of the current coordinate space so that it is located in the lower-left corner of the targeted window or view, as shown in Figure 3-1. This gives your code an anchor point at which to draw content. Even though the origin point can change relative to the screen, it always remains the same relative to your code.
The mapping from screen coordinates to window or view coordinates takes place in the current transformation matrix (CTM) of the Cocoa graphics context object. Cocoa applies the CTM automatically to any drawing calls you make, so you do not need to convert coordinate values yourself. You can modify the CTM though to change the position and orientation of the coordinate axes inside your view. (For more information, see “Transformation Operations.”)
The drawing system in Mac OS X is based on a PDF drawing model, which is a vector-based drawing model. Compared to a raster-based drawing model, where drawing commands operate on individual pixels, drawing commands in Mac OS X are specified using a fixed-scale drawing space, known as the user coordinate space. The system then maps the coordinates in this drawing space onto the actual pixels of the corresponding target device, such as a monitor or printer. The advantage of this model is that graphics drawn using vector commands scale nicely to any resolution device. As the device resolution increases, the system is able to use any extra pixels to create a crisper look to the graphics.
In order to maintain the precision inherent with a vector-based drawing system, drawing coordinates are specified using floating-point values instead of integers. The use of floating-point values for Mac OS X coordinates makes it possible for you to specify the location of your program's content very precisely. For the most part, you do not have to worry about how those values are eventually mapped to the screen or other output device. Instead, Cocoa takes care of this mapping for you.
Even though the drawing model is based on PDF, there are still times when you need to render pixel-based content. Bitmap images are a common way to create user interfaces, and your drawing code may need to make special adjustments to ensure that any bitmap images are drawn correctly on different resolution devices. Similarly, you may want to ensure that even your vector-based graphics align properly along pixel boundaries so that they do not have an anti-aliased appearance. Mac OS X provides numerous facilities to help you draw pixel-based content the way you want it.
The following sections provide more detail about the coordinate spaces used for drawing and rendering content. There also follows some tips on how to deal with pixel-specific rendering in your drawing code.
The user coordinate space in Cocoa is the environment you use for all your drawing commands. It represents a fixed scale coordinate space, which means that the drawing commands you issue in this space result in graphics whose size is consistent regardless of the resolution of the underlying device.
Units in the user space are based on the printer's point, which was used in the publishing industry to measure the size of content on the printed page. A single point is equivalent to 1/72 of an inch. Points were adopted by earlier versions of Mac OS as the standard resolution for content on the screen. Mac OS X continues to use the same effective “resolution” for user-space drawing.
Although a single point often corresponded directly to a pixel in the past, in Mac OS X, that may not be the case. Points are not tied to the resolution of any particular device. If you draw a rectangle whose width and height are exactly three points, that does not mean it will be rendered on the screen as a three-pixel by three-pixel rectangle. On a 144 dpi screen, the rectangle might be rendered using six pixels per side, and on a 600-dpi printer, the rectangle would require 25 pixels per side. The actual translation from points to pixels is device dependent and handled for you automatically by Mac OS X.
For all practical purposes, the user coordinate space is the only coordinate space you need to think about. There are some exceptions to this rule, however, and those are covered in “Doing Pixel-Exact Drawing.”
The device coordinate space refers to the native coordinate space used by the target device, whether it be a screen, printer, file, or some other device. Units in the device coordinate space are specified using pixels and the resolution of this space is device dependent. For example, most monitors have resolutions in the 100 dpi range but printers may have resolutions exceeding 600 dpi. There are some devices that do not have a fixed resolution, however. For example, PDF and EPS files are resolution independent and can scale their content to any resolution.
For Cocoa users, the device coordinate space is something you rarely have to worry about. Whenever you generate drawing commands, you always specify positions using user space coordinates. The only time that you might need to know about device space coordinates is when you are adjusting your drawn content to map more cleanly to a specific target device. For example, you might use device coordinates to align a path or image to specific pixel boundaries in order to prevent unwanted anti-aliasing. In such a situation, you can adjust your user space coordinates based on the resolution of the underlying device. For information on how to do this, see “Doing Pixel-Exact Drawing”
In Mac OS X v10.4 and earlier, Quartz and Cocoa treated screen devices as if their resolution were always 72 dpi, regardless of their actual resolution. This meant that for screen-based drawing, one point in user space was always equal to one pixel in device space. As screens advanced well past 100 dpi in resolution, the assumption that one point equaled one pixel began to cause problems. Most noticeably, everything became much smaller. In Mac OS X v10.4, the first steps at decoupling the point-pixel relationship took place.
In Mac OS X v10.4, support was added for resolution independence in application user interfaces. The initial implementation of this feature provides a way for you to decouple your application’s user space from the underlying device space manually. You do this by choosing a scale factor for your user interface. The scale factor causes user space content to be scaled by the specified amount. Code that is implemented properly for resolution independence should look fine (albeit bigger). Code that is not implemented properly may see alignment problems or pixel cracks along shape boundaries. To enable resolution independence in your application, launch Quartz Debug and choose Tools > Show User Interface Resolution, then set your scale factor. After changing the resolution, relaunch your application to see how it responds to the new resolution.
For the most part, Cocoa applications should not have to do anything special to handle resolution-independent UI. If you use the standard Cocoa views and drawing commands to draw your content, Cocoa automatically scales any content you draw using the current scale factor. For path-based content, your drawing code should require little or no changes. For images, though, you may need to take steps to make sure those images look good at higher scale factors. For example, you might need to create higher-resolution versions to take advantage of the increased screen resolution or to avoid the interpolation that can occur when scaling to a higher-resolution.
For more information about resolution independence and how it affects your code, see Resolution Independence Guidelines.
Last updated: 2007-10-31