Working with CGLayers


The CGLayer opaque data type, and the associated API, was added to the system starting with Mac OS X 10.4 Tiger. If your application must support older versions of the operating system, you will have to choose another offscreen drawing method. However in Tiger and above, CGLayer is usually a better method for creating an offscreen context than creating an offscreen bitmap.

Conceptually, a CGLayer is an offscreen cache for a Quartz 2D graphic. Note that a CGLayer is not necessarily an offscreen bitmap. The way the layer stores its graphic is an implementation detail that is private to Quartz 2D. The only assurance offered by a CGLayer is that the computer can reproduce a graphic as fast or faster when drawing the layer than it could by re-executing the drawing commands that placed the graphic on the layer. This means that a CGLayer is an excellent tool for caching graphics that you plan to use repeatedly.

A CGLayer's graphic need not be cached in a bitmap. The technique that the layer uses to store its graphics is entirely up to Quartz 2D itself. Because a CGLayer chooses its own internal representation, it can select a resolution-independent representation when the layer is drawn on a PDF context or a pixel buffer stored on the video card for layers that draw to the screen. This allows the operating system to tailor the operation of drawing the layer to another context so that it executes as quickly as possible.

Two examples illustrate the kinds of optimizations Quartz 2D might use when drawing with layers. If an application creates a CGLayer to store a graphic off-screen and then draws that layer many times to the display, Quartz 2D can recognize that the same layer is drawn repeatedly. It can move a bitmap of the layer's graphics to the video card and then reproduce that graphic on screen very quickly by simply copying the pixels using the power of the graphics card instead of draining the horsepower of the CPU.

When drawing a layer into a PDF context, Quartz 2D can create a separate PDF object to represent the layer's graphics and then re-use that object many times. Because the PDF commands to draw the object are likely to take up less space than the commands that draw the layer's graphics, the result is smaller PDF files. A PDF viewer is quite likely to be able to cache the layer's graphics again when it displays the file. That means that the PDF itself is quite likely to draw faster than if each copy of the layer graphic was redrawn explicitly.

From the programmer's perspective, CGLayers offer some other advantages over offscreen bitmaps. For example, code that uses CGLayers do not have to contend with a lot of the details surrounding the construction of an offscreen bitmap. CGLayers manage their own internal representations, which means that if the CGLayer uses an offscreen bitmap, the layer itself will manage the life cycle of the block of memory that contains the pixels.

Another example is when using an offscreen bitmap to cache an image, the application can draw the cached image by creating a CGImage on the offscreen pixel buffer and drawing that image on an appropriate destination. Because the pixel buffer behind a CGImage is immutable, however, programs using this technique must be careful to ensure that they do not draw into the pixel buffer while the CGImage exists. To put it another way, the CGImage must be recreated each time the application draws in the pixel buffer. CGLayers do not share this restriction. The contents of a CGLayer can accept new graphics at any time.

In contrast, however, an offscreen bitmap allows the program to directly access and manipulate the pixels that make up its image. A CGLayer may not even have a pixel representation backing it up. CGLayers are the preferred offscreen drawing mechanism in many instances, but if an application wants to access the offscreen's pixel buffer, a CGBitmapContext is the better choice.

Using CGLayers

The process of using a CGLayer is very straightforward. The entire CGLayer interface consists of a little more than a handful of routines.

The first step is to create the CGLayer itself. Layers have a fixed size, and they are associated with a particular graphics context. This is the graphics context that the layer will draw on most efficiently. In the second step, the application asks the layer for a graphics context that it can use to draw onto the layer itself. Quartz 2D records drawing commands sent to this context and decomposes them into a convenient representation that it can efficiently replay later. Once the layer has a graphic, drawing the layer will reproduce that graphic quickly. Usually the layer is drawn on to the same context that the program supplied when it created the layer.

Creating a CGLayer

The routine that creates CGLayers is CGLayerCreateWithContext. This routine takes three parameters. The first parameter is an already existing graphics context. Quartz 2D uses this context to obtain hints about how it should construct the layer. The library will choose a representation for the layer's graphics cache so that the layer's graphics can be redrawn on the source context as quickly as possible. The second parameter is a CGSize. This size establishes the bounds of the layer's drawing context. The last parameter is a CFDictionary that may allow you to tailor the layer further in the future. In Tiger's incarnation of the CGLayer API, Quartz does not use this dictionary, and this parameter should be NULL.

The context that you pass to CGLayerCreateWithContext only provides information that helps initialize the layer. When the layer is drawn to any context with the same characteristics, Quartz 2D will be able to draw the layer as quickly as possible. If you draw that layer to a different context, however, Quartz 2D will do its best to reproduce the graphic, but there may be a loss in terms of drawing performance or image quality.

Drawing into a CGLayer

The routine CGLayerGetContext returns a graphics context that Quartz 2D can use to draw on a layer. This is not the same context that was originally passed to CGLayerCreateWithContext. Like the other contexts, the one returned by this routine starts out with its origin in the lower left corner of the layer. The size of the drawing surface is the same as the size passed as a parameter when the program created the layer.

Drawing the Layer's Graphic Elsewhere

The CGContext interface includes two routines that draw the contents of a layer onto their graphics devices. CGContextDrawLayerAtPoint asks the context to draw the layer with its lower left corner coincident with a particular point in user space. CGContextDrawLayerInRect is similar with the obvious exception that it scales the layers graphic to fit into a particular rectangle.




Quartz 2D Graphics for Mac OS X Developers
Quartz 2D Graphics for Mac OS X Developers
ISBN: 0321336631
EAN: 2147483647
Year: 2006
Pages: 100

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net