Carbon applications have two scaling options: framework-scaled mode and magnified mode. You set these modes on a window-by-window basis by setting the appropriate attribute at window creation time. If you do not select a scale mode, the system assumes magnified mode by default. You can specify the scale mode of a window only at window creation time.
Framework-Scaled Mode
Magnified Mode
Detecting Scale Information
Coordinate Conversion in Carbon
Custom Drawing in Carbon
Unsupported Technologies
As described previously, a window can use the framework-scaled mode if it uses HIView-based controls (that is, it uses compositing mode) and draws exclusively with Quartz. At drawing time, a scaling transform is applied to the Quartz context used by the views. Also, in order to support older functions, any window coordinate information (window bounds, mouse position, and so on) is automatically translated to reflect the proper window- or view-centric origin before being passed to the application.
A major benefit of framework-scaled mode is that windows loaded from nib files automatically work at all scale factors with no need to reposition their contents.
You specify framework-scaled mode by setting the kWindowFrameworkScaledAttribute attribute at window creation time or by choosing Framework Scaled for the Scaling popup button in the window inspector in Interface Builder version 2.5 and later.
While specifying framework-scaled mode means most of the scaling work is handled for you, you still need to supply higher-resolution versions of any custom artwork, such as icons, background images, and so on.
Magnified mode is the default rendering mode. If the scale factor is not 1.0, all windows that are not tagged as being in framework-scaled mode are scaled in magnified mode. As described previously, the window is simply scaled to match the scale factor.
Important: Because magnified windows do not look as crisp as properly scaled windows, you should adopt framework scaling as soon as possible.
In magnified mode, all onscreen coordinates are mapped to their user space equivalents when passed to the application. For example, if the scale factor is 2.0, a mouse click onscreen at a particular pixel is mapped to its window or view-centric equivalent location when passed in a mouse-down event.
To determine the scale factor for your application, you can use the HIGetScaleFactor function:
CGFloat HIGetScaleFactor (void); |
If you need to determine the scale mode for a particular window (and also the application scale factor), you can call the HIWindowGetScaleMode function:
OSStatus HIWindowGetScaleMode ( |
HIWindowRef inWindow, |
HIWindowScaleMode *outMode, |
CGFloat *outScaleFactor); |
On output, outMode returns one of the following values:
kHIWindowScaleModeUnscaledThe window is not scaled at all because the scale factor is 1.0.
kHIWindowScaleModeMagnifiedThe window‘s backing store is being magnified because the scale factor is not equal to 1.0 and because the window was not created with the framework-scaled attribute.
kHIWindowScaleModeFrameworkScaledThe window‘s contents are scaled to match the scale factor because the scale factor is not equal to 1.0 and because the window was created with the framework-scaled attribute.
Note: A fourth scale mode named kHIWindowScaleModeApplicationScaled was available in Mac OS X v10.4 but was never fully implemented and is not supported at all in Mac OS X v10.5 and later.
Because the scale mode in Carbon applications can be on a window-by-window basis, you may often need to convert between the various coordinate systems involved. The HIGeometry programming interface (see HIGeometry Reference) provides three functions that simplify conversion:
HIPointConvert to translate an HIPoint structure.
HIRectConvert to translate an HIRect structure. Note that the HIRect structure has an organization different from that of the older QuickDraw Rect structure.
HISizeConvert to translate an HISize structure.
These conversion functions require you to specify the source and destination coordinate spaces as well as any associated objects, if required. For example, if you wanted to translate a point into view coordinates, you must specify the HIView to which the coordinates refer. You specify the coordinate spaces by passing the following constants:
kHICoordSpace72DPIGlobal, which specifies the old global coordinate system defined by QuickDraw. When the scale factor is 1.0, this space is equivalent to kHICoordSpaceScreenPixel.
kHICoordSpaceScreenPixel, which is the coordinate space defined by the actual screen pixels.
kHICoordSpaceWindow, which specifies a window-centric coordinate system, with the origin (0,0) being the top-left corner of the window's structure region.
kHICoordSpaceView, which specifies an HIView-centric coordinate system. The origin (0,0) is the top-left corner of the view.
The conversion functions take floating-point coordinates, which means that rounding may be necessary in certain cases. Which way to round depends on whether the system is more forgiving of overstating or understating the value. For example:
When the coordinate is used to define some sort of maximal area, you should outset the value. That is, round the value so that it defines a larger area rather a smaller one. For example, you should outset coordinate values that define a view's structure shape, because that area defines the maximum bounds into which the view can draw.
When defining a minimal area, you should inset the value. For example, you should inset the coordinate values for a view's opaque region, because that area defines the largest area that can be assumed to be opaque.
You can use the Quartz 2D functions CGRectInset and CGRectIntegral to simplify inset and outset operations. The BSD Library functions ceil and floor (available in math.h) may also be useful.
Keep in mind that HIShapeRef values take only integer coordinates. If you attempt to create a shape from floating-point coordinates (for example, by calling HIShapeCreateWithRect on an HIRect object), the call automatically rounds any non-integer coordinates to outset the shape. To avoid unexpected results, you should round any coordinates appropriately (inset or outset) before creating an HIShape based upon it.
If your application uses custom controls or menus, you may need to make some changes to make them compatible with resolution independence.
If you are still using QuickDraw to draw, you should adopt Quartz. If you are using the Appearance Manager to draw control elements, use HITheme (which is Quartz-savvy) instead.
In framework-scaled mode, the Quartz context passed to your custom view in the kEventControlDraw event has already been transformed to match the scale factor, so you probably won't need to update your drawing code.
If your application still uses custom MDEFs, the Menu Manager creates windows to hold them and scales them appropriately, so they are effectively in magnified mode. However, you should consider updating your MDEFs to custom HIView-based menus.
When using view-based menus, the Menu Manager can automatically scale them in framework-scaled mode. Currently a workaround exists that allows kEventMenuDrawItem and kEventMenuDrawItemContent handlers to use QuickDraw calls even in framework-scaled mode. The standard menu view creates a temporary GWorld object and sets it to the current QuickDraw port before sending any menu drawing events. After the draw event, the Menu Manager copies the contents of the graphics world into the view. However, this workaround should be considered a temporary fix and you should plan to update your menu drawing handlers to draw into the supplied CGContext event parameter.
The following Carbon technologies will not be updated to support resolution independence:
TextEdit. Applications should use MLTE, the editable Unicode text control, or HITextView instead.
The edit text control. Applications should use the editable Unicode text control or HITextView instead.
The list box control. Applications should use the data browser control instead.
Last updated: 2007-05-04