Apple Developer Connection
Member Login Log In | Not a Member? Contact ADC

< Previous PageNext Page > Hide TOC

Doing Pixel-Exact Drawing

Because screens are relatively low-resolution devices, drawing glitches are often more noticeable on a screen than they are on higher-resolution devices such as printers. Drawing glitches can occur when you render content in a way that requires tweaking to match the underlying pixels sent to the screen. For example, images and shapes drawn on non-pixel boundaries might require aliasing and therefore might appear less crisp than those drawn exactly on pixel boundaries. In addition, scaling an image to fit into a different-sized area requires interpolation, which can introduce artifacts and graininess.

Although pixel-alignment issues can occur on any version of Mac OS X, they are more likely to occur as the operating system changes to support resolution independence. Under resolution independence, units in the user coordinate space and device coordinate space are no longer required to maintain a one-to-one relationship. For high-resolution screens, this means that a single unit in user space may be backed by multiple pixels in device space. So even if your user-space coordinates fall on integral unit boundaries, they may still be misaligned in device space. The presence of extra pixels can also lead to pixel cracks, which occur when misaligned shapes leave small gaps because they do not fill the intended drawing area entirely.

If your images or shapes are not drawing the way you expect, or if your graphics display evidence of pixel cracks, you can remove many of these issues by adjusting the coordinate values you use to draw your content. The following steps are not required if the current scale factor is 1.0 but would be required for other scale factors.

  1. Convert the user-space point, size, or rectangle value to device space.

  2. Normalize the value in device space so that it is aligned to the appropriate pixel boundary.

  3. Convert the normalized value back to user space.

  4. Draw your content using the adjusted value.

Mac OS X provides several functions for normalizing coordinate values once they are in device space, including the following:

The sections that follow discuss the options for converting coordinates to and from device space. For additional information about supporting resolution independence, see “Resolution-Independent User Interface.”

In this section:

Accessing the Current Scale Factor
Converting Coordinate Values


Accessing the Current Scale Factor

Knowing the current scale factor can help you make decisions about how best to render your content. The NSWindow and NSScreen classes both include a userSpaceScaleFactor method that you can call to obtain the current scale factor, if any, for your application. In Mac OS X v10.5 and earlier, this method usually returns 1.0, indicating that the user space and device space have the same resolution (where one point equals one pixel). At some point though, this method may return a value that is greater than 1.0. For example, a value of 1.25 would indicate a screen resolution of approximately 90 dpi, while a value of 2.0 would indicate a screen resolution of 144 dpi.

If you want to know the actual resolution of a particular screen, the NSScreen class includes information about the display resolution in its device description dictionary (accessed using the deviceDescription method). You can use this information (instead of multiplying scale factors) to determine the appropriate resolution to use for your images.

Converting Coordinate Values

In Mac OS X v10.5, several methods were added to NSView to simplify the conversion between user space and device space coordinates:

These convenience methods make it possible to convert values to and from the base (device) coordinate system. They take into account the current backing store configuration for the view, including whether it is backed by a layer.

To change the coordinate values of an NSPoint structure, the beginning of your view’s drawRect: method might have code similar to the following:

- (void)drawRect:(NSRect)rect
{
    NSPoint myPoint = NSMakePoint(1.0, 2.0);
    CGFloat scaleFactor = [[self window] userSpaceScaleFactor];
    if (scaleFactor != 1.0)
    {
        NSPoint    tempPoint = [self convertPointToBase:myPoint];
        tempPoint.x = floor(tempPoint.x);
        tempPoint.y = floor(tempPoint.y);
        myPoint = [self convertPointFromBase:tempPoint];
    }
    // Draw the content at myPoint
}

It is up to you to determine which normalization function is best suited for your drawing code. The preceding example uses the floor function to normalize the origin of the given shape but you might use a combination of floor and ceil depending on the position of other content in your view.



< Previous PageNext Page > Hide TOC


Last updated: 2007-10-31




Did this document help you?
Yes: Tell us what works for you.

It’s good, but: Report typos, inaccuracies, and so forth.

It wasn’t helpful: Tell us what would have helped.
Get information on Apple products.
Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Copyright © 2007 Apple Inc.
All rights reserved. | Terms of use | Privacy Notice