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

< Previous PageNext Page > Hide TOC

Painting Stencil Patterns

There are five steps you need to perform to paint a stencil pattern:

  1. “Write a Callback Function That Draws a Stencil Pattern Cell”

  2. “Set Up the Stencil Pattern Color Space”

  3. “Set Up the Anatomy of the Stencil Pattern”

  4. “Specify the Stencil Pattern as a Fill or Stroke Pattern”

  5. “Draw With the Stencil Pattern”

These are actually the same steps you use to paint a colored pattern. The difference between the two is how you set up color information. Each of the subsequent sections explains how to implement each step. You can see how all the steps fit together in “A Complete Stencil Pattern Painting Function.”

Write a Callback Function That Draws a Stencil Pattern Cell

The callback you write for drawing a stencil pattern follows the same form as that described for a colored pattern cell. See “Write a Callback Function That Draws a Colored Pattern Cell.” The only difference is that your drawing callback does not specify any color. The pattern cell shown in Figure 6-10 does not get its color from the drawing callback. The color is set outside the drawing color in the pattern color space.


Figure 6-10  A stencil pattern cell

A stencil pattern cell

Take a look at the code in Listing 6-6, which draws the pattern cell shown in Figure 6-10. Notice that the code simply creates a path and fills the path. The code does not set color.

Listing 6-6  A drawing callback that draws a stencil pattern cell

#define PSIZE 16    // size of the pattern cell
 
static void MyDrawStencilStar (void *info, CGContextRef myContext)
{
    int k;
    double r, theta;
 
    r = 0.8 * PSIZE / 2;
    theta = 2 * M_PI * (2.0 / 5.0); // 144 degrees
 
    CGContextTranslateCTM (myContext, PSIZE/2, PSIZE/2);
 
    CGContextMoveToPoint(myContext, 0, r);
    for (k = 1; k < 5; k++) {
        CGContextAddLineToPoint (myContext,
                    r * sin(k * theta),
                    r * cos(k * theta));
    }
    CGContextClosePath(myContext);
    CGContextFillPath(myContext);
}

Set Up the Stencil Pattern Color Space

Stencil patterns require that you set up a pattern color space for Quartz to paint with, as shown in Listing 6-7. A detailed explanation for each numbered line of code follows the listing.

Listing 6-7  Code that creates a pattern color space for a stencil pattern

CGPatternRef pattern;
CGColorSpaceRef baseSpace;
CGColorSpaceRef patternSpace;
 
baseSpace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);// 1
patternSpace = CGColorSpaceCreatePattern (baseSpace);// 2
CGContextSetFillColorSpace (myContext, patternSpace);// 3
CGColorSpaceRelease(patternSpace);// 4
CGColorSpaceRelease(baseSpace);// 5

Here’s what the code does:

  1. In Mac OS X v10.4, this function creates a generic RGB space. Generic color spaces leave color matching to the system. For more information, see “Creating Generic Color Spaces.”

  2. Creates a pattern color space. The color space you supply specifies how colors are represented for the pattern. Later, when you set colors for the pattern, you must set them using the pattern color space. For this example, you will need to specify color using RGB values.

  3. Sets the color space to use when filling a pattern. You can set a stroke color space by calling the function CGContextSetStrokeColorSpace.

  4. Releases the base color space object.

  5. Releases the pattern color space object.

Set Up the Anatomy of the Stencil Pattern

You specify information about the anatomy of a pattern the way you would for a colored pattern—by calling the function CGPatternCreate. The only difference is that you pass false for the isColored parameter. See “Set Up the Anatomy of the Colored Pattern” for more information on the parameters you supply to the CGPatternCreate function.

Specify the Stencil Pattern as a Fill or Stroke Pattern

You can use your pattern for filling or stroking by calling the appropriate function, CGContextSetFillPattern or CGContextSetStrokePattern. Quartz uses your pattern for any subsequent filling or stroking.

These functions each take three parameters:

A stencil pattern does not supply a color in the drawing callback, so you must pass a color to the fill or stroke functions to inform Quartz what color to us. Listing 6-8 shows an example of how to set color for a stencil pattern. The values in the color array will be interpreted by Quartz in the color space you set up earlier. Because this example uses device RGB, the color array contains values for red, green, and blue components. The fourth value specifies the opacity of the color.

Listing 6-8  Code that sets opacity for a colored pattern

static const float color[4] = { 0, 1, 1, 0.5 }; //cyan, 50% transparent
 
CGContextSetFillPattern (myContext, myPattern, color);

Draw With the Stencil Pattern

After you’ve completed the previous steps, you can call any Quartz 2D function that paints. Your pattern is used as the “paint.” For example, you can call CGContextStrokePath, CGContextFillPath, CGContextFillRect, or any other function that paints.

A Complete Stencil Pattern Painting Function

The code in Listing 6-9 contains a function that paints a stencil pattern. The function incorporates all the steps discussed previously. A detailed explanation for each numbered line of code follows the listing.

Listing 6-9  A function that paints a stencil pattern

#define PSIZE 16
 
void MyStencilPatternPainting (CGContextRef myContext,
                                const Rect *windowRect)
{
    CGPatternRef pattern;
    CGColorSpaceRef baseSpace;
    CGColorSpaceRef patternSpace;
    static const float color[4] = { 0, 1, 0, 1 };// 1
    static const CGPatternCallbacks callbacks = {0, &drawStar, NULL};// 2
 
    baseSpace = CGColorSpaceCreateDeviceRGB ();// 3
    patternSpace = CGColorSpaceCreatePattern (baseSpace);// 4
    CGContextSetFillColorSpace (myContext, patternSpace);// 5
    CGColorSpaceRelease (patternSpace);
    CGColorSpaceRelease (baseSpace);
    pattern = CGPatternCreate(NULL, CGRectMake(0, 0, PSIZE, PSIZE),// 6
                  CGAffineTransformIdentity, PSIZE, PSIZE,
                  kCGPatternTilingConstantSpacing,
                  false, &callbacks);
    CGContextSetFillPattern (myContext, pattern, color);// 7
    CGPatternRelease (pattern);// 8
    CGContextFillRect (myContext,CGRectMake (0,0,PSIZE*20,PSIZE*20));// 9
}

Here’s what the code does:

  1. Declares an array to hold a color value and sets the value (which will be in RGB color space) to opaque green.

  2. Declares and fills a callbacks structure, passing 0 as the version and a pointer to a drawing callback function. This example does not provide a release info callback, so that field is set to NULL.

  3. Creates an RGB device color space. If the pattern is drawn to a display, you need to supply this type of color space.

  4. Creates a pattern color space object from the RGB device color space.

  5. Sets the fill color space to the pattern color space object you just created.

  6. Creates a pattern object. Note that the second to last parameter—the isColored parameter—is false. Stencil patterns do not supply color, so you must pass false for this parameter. All other parameters are similar to those passed for the colored pattern example. See “A Complete Colored Pattern Painting Function.”

  7. Sets the fill pattern, passing the color array declared previously.

  8. Releases the CGPattern object.

  9. Fills a rectangle. Quartz fills the rectangle using the pattern you just set up.



< Previous PageNext Page > Hide TOC


Last updated: 2007-12-11




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