The Quartz 2D Drawing Model


Having examined the features of Quartz 2D, this chapter now turns our attention to the way applications use the library to create graphics. To use a library efficiently you need to understand what real-world objects and processes the library models. This is as true in graphics as it is in any computer discipline. Each graphics library has a different collection of drawing primitives, different ways of handling color, and drawing techniques that are particular to that graphics library. All of these give the library a unique character. They not only establish the capabilities of the library, but they also define its limits. Collectively these abstractions and processes are called the imaging model of the library. The next few sections explore the Quartz 2D imaging model. The goal is to introduce some of the important concepts that you have to understand in order to make effective use of the Quartz 2D API. Later chapters will get into the details of putting the imaging model to work for you.

Drawing Primitives

Raster-oriented libraries like QuickDraw create drawings using metaphors such as the "graphics pen." QuickDraw uses the graphics pen to trace out lines or ovals on the graphics device. Quartz 2D, in contrast, uses object-like drawing primitives. Quartz 2D applications construct shapes, images, or text first, and then they ask the library to draw them. The objects take their attributes, colors and the like, from the graphics environment in which they are drawn.

Given the richness of the graphics that Quartz 2D creates, it may surprise you to learn that Quartz 2D really only supports three different drawing primitives, sampled images, line art, and text. The real flexibility of Quartz 2D is the rich set of drawing attributes at your disposal when you draw these primitives, as well as the flexibility you enjoy to use Quartz 2D to position and transform these primitives.

Line art includes many of the same drawing primitives found in other graphics libraries. Using Quartz 2D, your applications create objects called paths. In a way, paths are similar to the outlines printed in a child's coloring book. Those outlines are really just collections of straight and curved line segments that encircle an area of the page. The colored shapes combine to create a finished image. Quartz 2D uses paths in a similar fashion.

When drawing line art, the application creates paths and then colors those paths to create an image. Unlike the outlines in the coloring book, however, the edges of a path are infinitely thin. This is a crucial aspect of paths that makes them a resolution independent drawing primitive. More will be said about paths and crayons later in this chapter. Chapter 6, "Line ArtBuilding Paths," and Chapter 7, "Line ArtDrawing," explore the topic of drawing with paths in detail.

A sampled image is a pixel-based picture. One way to describe the origin of the term is to consider the way a Digital Camera takes photographs. When you take a picture with a digital camera, the camera takes the light entering through the lens and projects it onto a special computer chip called a Charge-Coupled Device (CCD). This device selects light at various points on the chip and records, or samples it. The camera assigns the pixels in a picture different colors for those samples. The resulting sampled images are stored on the camera, often in JPEG format, until you are ready to transfer them to a computer or print them.

When an imaging device like a camera or scanner samples a scene and generates an image, it usually does it at a fixed resolution. Quartz 2D has the ability to re-sample the pixels. As it does so, it can synthesize new pixels based on the color samples. Using this capability the library treats a sampled image as a resolution independent drawing primitive in spite of its fixed resolution. Chapter 8, "Image Basics," describes the resampling process and describes how Quartz 2D represents images. That chapter also describes how to create images by drawing with Quartz 2D. Chapter 9, "Importing and Exporting Images," explores tools for importing and exporting images into popular image file formats like JPEG, PNG, and TIFF.

The third Quartz 2D drawing primitive is text. Quartz 2D treats works with text from a very low-level, drawing-oriented perspective. The library knows how to work with the Mac OS X font system to retrieve the paths it needs to draw glyphs. Once it has the paths in hand, Quartz draws text using the same facilities it uses to draw other line art.

Because Quartz treats text at such a low level, it is impractical for most applications to use Quartz 2D directly to draw text. Mac OS X offers higher level text services in each of the application frameworks. Applications will typically use these higher level text services rather than draw with Quartz 2D directly. Nevertheless, applications with very special text drawing needs may find Quartz 2D's facilities very helpful. Chapter 11, "Drawing Text with Quartz 2D," discusses the Mac OS X text system and the role of Quartz 2D in that system. It also has an example of creating a text special effect using Quartz 2D.

This small set of primitive drawing types may seem rather restrictive at first, but keep in mind that Quartz 2D's drawing model is a descendent of PDF. PDF in turn is an evolution of PostScript. Computers represent the images for everything from cereal boxes to books (this one included!) using one of these technologies. Even with this small set of simple building blocks, Quartz 2D allows you to create very rich and expressive graphics.

The Graphics Context

The bridge that the computer forges between an application and an output device is called the graphics context. Most libraries have some kind of graphics context. QuickDraw, for example, uses a structure called the GrafPort. The Java 2D graphics context is an instance of the Graphics2D class. The opaque data type that represents a graphics context for Quartz 2D is CGContext. Application code keeps track of CGContexts using the CGContextRef data type.

A CGContext keeps track of all the drawing parameters of the graphics environment. One of the most important is the coordinate system in which your application draws its graphics primitives. The CGContextRef also keeps track of the current drawing colors, the antialiasing settings, and many other drawing options. Chapter 4 provides descriptions of the fields of a CGContext.

The first step in any Quartz 2D drawing is obtaining a CGContext. Each output device has a particular type of context. That context understands how to communicate with the device and is familiar with the peculiarities of the device's graphics engine. Your application will create contexts for different devices using different Core Graphics routines. All CGContexts have a common interface that abstracts away the device details which allows applications to treat all devices uniformly. Quartz 2D code sends graphics to an offscreen bitmap or to a high-resolution printer with equal facility. Chapter 4 discusses CGContexts in more detail and demonstrates how to create contexts on many graphics devices.

The abstract drawing interface defines the character of the Quartz 2D drawing model. The sections that follow describe some consequences of supporting a broad range of graphics devices. They provide a high-level overview of drawing with Quartz 2D.

Where Have the Pixels Gone?

Most graphics devices, from display screens to printers, use pixels at some level. Graphics libraries like QuickDraw on the Macintosh, or GDI on Windows, incorporate pixels directly into their drawing models. For example, QuickDraw expresses the size of its graphics pen in pixels. Their coordinate systems address individual pixels, and much of the legend and lore in learning the libraries concern efficient ways to shuffle pixels around.

Quartz 2D draws to many of the same pixel-based devices that QuickDraw supports. Quartz 2D is not limited to pixel-based devices alone, though. Quartz 2D is device and resolution independent. In addition to pixel-based graphics devices, Quartz 2D also supports drawing destinations like PDF files and PostScript printers where pixels are not part of the device's drawing environment. The Quartz 2D imaging model could drive other devices, like laser cutters or pen plotters, that are not pixel-oriented.

Because it supports such a broad range of devices, the Quartz 2D imaging model doesn't rely on pixels. This fact can be shocking and somewhat disquieting for a novice Quartz 2D programmer. This is particularly true of programmers familiar with raster graphics libraries. Working with Quartz requires them to abandon many of the drawing techniques they have relied on for years.

Instead of drawing pixels, a Quartz 2D application draws the three resolution independent primitives we described earlier in this chapter. Quartz 2D transfers those drawing primitives to a raster device such as a window or bitmap with a three-phase process. The phases are drawing, mapping, and rasterization. Figure 3.2 illustrates all three drawing steps applied to a simple drawing.

Figure 3.2. The Quartz 2D Drawing Process

1. DrawingThe application draws a picture in user space. In this case the application creates a path that outlines a square. The corners of the path are specified in user space coordinates.

2. MappingThe application uses an affine transform to describe a mapping between user space and device space. In the figure, the transformation moves the origin of user space to the right. It also rotates the coordinate system counter-clockwise by 30 degrees. The figure shows how the affine transform maps the square path onto the device's pixel grid.

3. RasterizationIn the third step the computer selects which pixels to color. Figure 3.2 uses an algorithm that colors every pixel the square touches. As we will see, Quartz 2D often uses more sophisticated algorithms.


In the first step, drawing, a program creates graphics primitives and sends them to a CGContext. Line art consists of a number of points that define a path. Images draw in rectangles, and text is drawn by placing glyphs at particular points in the drawing area. All of these require the application to specify a location for the primitive in the context's coordinate system.

That coordinate system maintains the resolution independence that is characteristic of the Quartz 2D library. Graphics devices have their own coordinate systems, but those are typically tied to implementation details of the device. To maintain its device independence, a CGContext does not expose the device's coordinate system for creating graphics primitives. Instead, the CGContext supplies a coordinate system that is only indirectly related to the coordinates of the output device. As a program draws each primitive, Quartz 2D maps that primitive from the context's coordinate space to the device's. In the lingo of Quartz 2D, the abstract coordinate system is called user space. This is the coordinate system in which programs construct graphics primitives. The coordinate system of the device goes by the prosaic name device space.

The figure uses black to represent graphics as they are interpreted in user space. The gray portions of the figure are part of device space. You may note that the graphics drawn in user space, the black portions of the figure, are much smoother than those drawn in device space. Keep in mind that user space is a continuous space. It represents graphics mathematically and does not have discrete pixels or a fixed resolution. The device space we've represented in the figure does have a fixed resolution and discrete pixels. The grid in Figure 3.2 represents the boundaries of those pixels.

In the second step, Quartz 2D maps the graphics from user space to device space with a coordinate transformation. The library represents this mapping using a mathematical tool called an affine transformation. In exploring the features of Quartz 2D, it was mentioned that all affine transformations are combinations of translations, rotations, and scalings. Chapter 5 describes the characteristics of transformations and the API that creates them. That chapter describes process of setting up the transformation between user space and the device. At this point, it is enough to realize that applications build their primitives in a coordinate system that is independent of the device. Quartz 2D moves the graphics from user space to the device's coordinate system and begins the rasterization step.

After moving graphics to the device coordinate system, the library decides how to reproduce the graphics on the device. The actual technique used in this final step depends on the particular device. We're now going to explore the common case of drawing to a raster device.

To generate the final image, Quartz figures out which pixels it needs to color and what color the pixels should be. The computer uses paths as the outlines of areas in the device and colors the pixels inside those regions just like the child filling in the outlines of a coloring book. The computer also resamples images, guided by location of pixels on the device. This entire process of converting the drawing primitives into pixels is known as rasterization.

When working with Quartz 2D, applications concern themselves with setting up the transformation from user space to the device and creating graphics primitives that create the image they want to draw. Code inside the library handles the rasterization step, although applications do have some control over rasterization options.

Drawing graphics in one coordinate system only to have the computer move them to another can be the source of confusion for new Quartz developers. This mapping step, however, is crucial to the device and resolution independence of the graphics library. It also can simplify many drawing tasks. For example, drawing rotated text is as easy as changing the user space transformation and drawing the text. There is no need to draw the text into an offscreen graphics environment and then map the pixels back to the display.

This chapter just described the drawing steps that Quartz 2D goes though to create graphics on a raster device. The first two steps of the drawing process, drawing and mapping, are largely device independent operations. The third step, rasterization, really only applies for raster devices like windows and off-screen bitmaps. For output devices that don't have pixels, this third step might proceed differently. For example, a vector plotter or laser cutter might replace the rasterization step with commands that move the plotters pen or the cutter's laser. The advantage of the Quartz model is that the application need only concern itself with how to draw its graphics properly in user space and can use Quartz to handle the details of converting drawings to specific devices.

Drawing graphics with Quartz 2D involves laying down primitives in user space. The final image depends on the order that primitives are drawn in that coordinate system. Quartz 2D handles the layering of graphics images using a technique called the Painter's Model. We discuss this aspect of the drawing model next.

The Painter's Model

An application can easily arrange graphics horizontally and vertically in user space simply using the coordinate system of that drawing environment. To establish the back to front ordering of graphics primitives, the z-order of the elements, Quartz 2D uses an drawing technique known as the Painter's Model.

When an artist is working with oil paints on canvas, they have to be very careful with the order that they lay paint down. For a landscape scene, that painter must first paint the blue sky in the background. He layers in the mountains that form the skyline at the back of the scene. Next, he would carefully add the trees of a forest in the middle depths of the scene. The last elements are the flowers, field, cabin and windmill that live in the picture's foreground.

Quartz 2D works in much the same way. A newly created graphics context is a blank canvas. Applications build graphics by layering graphics primitives onto this canvas. Compositing is the process of combining new graphics primitives with the graphics that are already in the context. Quartz 2D's compositing integrates direct support for alpha channel transparency. Drawings can combine translucent and opaque graphics primitives in the same graphic.

To continue the analogy, you can think of colors in Quartz as the paint used to create the image. Quartz allows each color to have an alpha channel that describes the translucency of that color. Primitives drawn with opaque colors completely replace the drawing context beneath them. Paints with more transparency, corresponding to lower alpha channel values, allow more of the graphics already drawn into the context to show through.

When layering line art into a context, Quartz has to convert paths into a set of pixels to color. This process has been touched upon briefly a couple of times but will now be looked at in more depth.

The Crayon Model

Painters are not the only artists who have inspired the Mac OS X graphics system. Earlier paths were described in terms of a child's coloring book, so why not call the technique of working with paths the Crayon Model?

When a young child uses a crayon to draw a Valentine's Day card, he draws the outline of a heart first and then colors it in. Quartz 2D uses similar steps to draw a heart into a graphics context. In the Crayon Model metaphor, user space plays the role of the Valentine's Day card. Drawing code outlines a heart shape with a path and asks the library to color in that outline.

Chapter 6 discusses paths and how to construct them. For now, you should know that Quartz defines paths using a mathematical construct called a bezier curve. Unlike the outlines drawn in a coloring book, bezier curves describe shapes with infinitely thin boundaries. This means that the curves are resolution independent. The computer can rasterize the curve at any resolution.

After your application creates a path in user space, it can ask Quartz 2D to either fill the inside of that path with a color or trace its outline with a line. Filling the path creates a solid shape. This is the closest analogy to the Crayon Model as it involves coloring between the lines just as you would do in a coloring book. Tracing the outline of the path is called stroking the path. It would be like emphasizing the lines of the coloring book by tracing them with an extra wide crayon.

Quartz 2D uses paths for more than just drawing. Programs can use a path to define a clipping area for a CGContext. Once the application sets up the clipping path, the computer will clip any subsequent drawing in that context to the interior of the path. The computer will even antialias the drawing against the edges of the clipping path.




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