There are five steps you need to perform to paint a colored pattern:
These are the same steps you use to paint a stencil 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 Colored Pattern Painting Function.”
What a pattern cell looks like is entirely up to you. For this example, the code in Listing 6-1 draws the pattern cell shown in Figure 6-2. Recall that the black line surrounding the pattern cell is not part of the cell; it’s drawn to show that the bounds of the pattern cell are larger than the rectangles painted by the code. You specify the pattern size to Quartz later.
Your pattern cell drawing function is a callback that follows this form:
typedef void (*CGPatternDrawPatternCallback) ( |
void *info, |
CGContextRef context |
); |
You can name your callback whatever you like. The one in Listing 6-1 is named MyDrawColoredPattern. The callback takes two parameters:
info, a generic pointer to private data associated with the pattern. This parameter is optional; you can pass NULL. The data passed to your callback is the same data you supply later, when you create the pattern.
context, the graphics context for drawing the pattern cell.
The pattern cell drawn by the code in Listing 6-1 is arbitrary. Your code draws whatever is appropriate for the pattern you create. These details about the code are important:
The pattern size is declared. You need to keep the pattern size in mind as you write your drawing code. Here, the size is declared as a global. The drawing function doesn’t specifically refer to the size, except in a comment. Later, you specify the pattern size to Quartz 2D. See “Set Up the Anatomy of the Colored Pattern.”
The drawing function follows the prototype defined by the CGPatternDrawPatternCallback callback type definition.
The drawing performed in the code sets colors, which makes this a colored pattern.
Listing 6-1 A drawing callback that draws a colored pattern cell
#define H_PATTERN_SIZE 16 |
#define V_PATTERN_SIZE 18 |
void MyDrawColoredPattern (void *info, CGContextRef myContext) |
{ |
float subunit = 5; // the pattern cell itself is 16 by 18 |
CGRect myRect1 = {{0,0}, {subunit, subunit}}, |
myRect2 = {{subunit, subunit}, {subunit, subunit}}, |
myRect3 = {{0,subunit}, {subunit, subunit}}, |
myRect4 = {{subunit,0}, {subunit, subunit}}; |
CGContextSetRGBFillColor (myContext, 0, 0, 1, 0.5); |
CGContextFillRect (myContext, myRect1); |
CGContextSetRGBFillColor (myContext, 1, 0, 0, 0.5); |
CGContextFillRect (myContext, myRect2); |
CGContextSetRGBFillColor (myContext, 0, 1, 0, 0.5); |
CGContextFillRect (myContext, myRect3); |
CGContextSetRGBFillColor (myContext, .5, 0, .5, 0.5); |
CGContextFillRect (myContext, myRect4); |
} |
The code in Listing 6-1 uses colors to draw the pattern cell. You must ensure that Quartz paints with the colors you use in your drawing routine by setting the base pattern color space to NULL, as shown in Listing 6-2. A detailed explanation for each numbered line of code follows the listing.
Listing 6-2 Creating a base pattern color space
CGColorSpaceRef patternSpace; |
patternSpace = CGColorSpaceCreatePattern (NULL);// 1 |
CGContextSetFillColorSpace (myContext, patternSpace);// 2 |
CGColorSpaceRelease (patternSpace);// 3 |
Here’s what the code does:
Creates a pattern color space appropriate for a colored pattern by calling the function CGColorSpaceCreatePattern, passing NULL as the base color space.
Sets the fill color space to the pattern color space. If you are stroking your pattern, call CGContextSetStrokeColorSpace.
Releases the pattern color space.
Information about the anatomy of a pattern is kept in a CGPattern object. You create a CGPattern object by calling the function CGPatternCreate, whose prototype is shown in Listing 6-3.
Listing 6-3 The CGPatternCreate function prototype
CGPatternRef CGPatternCreate ( void *info, |
CGRect bounds, |
CGAffineTransform matrix, |
float xStep, |
float yStep, |
CGPatternTiling tiling, |
int isColored, |
const CGPatternCallbacks *callbacks ); |
The info parameter is a pointer to data you want to pass to your drawing callback. This is the same pointer discussed in “Write a Callback Function That Draws a Colored Pattern Cell.”
You specify the size of the pattern cell in the bounds parameter. The matrix parameter is where you specify the pattern matrix, which maps the pattern coordinate system to the default coordinate system of the graphics context. Use the identity matrix if you want to draw the pattern using the same coordinate system as the graphics context. The xStep and yStep parameters specify the horizontal and vertical spacing between cells in the pattern coordinate system. See “The Anatomy of a Pattern” to review information on bounds, pattern matrix, and spacing.
The tiling parameter can be one of three values:
See “Tiling” to review information on tiling.
The isColored parameter specifies whether the pattern cell is a colored pattern (true) or a stencil pattern (false). If you pass true here, your drawing pattern callback specifies the pattern color, and you must set the pattern color space to the colored pattern color space (see “Set Up the Colored Pattern Color Space”).
The last parameter you pass to the function CGPatternCreate is a pointer to a CGPatternCallbacks data structure. This structure has three fields:
struct CGPatternCallbacks |
{ |
unsigned int version; |
CGPatternDrawPatternCallback drawPattern; |
CGPatternReleaseInfoCallback releaseInfo; |
}; |
You set the version field to 0. The drawPattern field is a pointer to your drawing callback. The releaseInfo field is a pointer to a callback that’s invoked when the CGPattern object is released, to release storage for the info parameter you passed to your drawing callback. If you didn’t pass any data in this parameter, you set this field to NULL.
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:
The graphics context
The CGPattern object that you created previously
An array of color components
Although colored patterns supply their own color, you must pass a single alpha value to inform Quartz of the overall opacity of the pattern when it’s drawn. Alpha can vary from 1 (completely opaque) to 0 (completely transparent). Listing 6-4 shows an example of how to set opacity for a colored pattern used to fill.
Listing 6-4 Code that sets opacity for a colored pattern that’s used to fill
float alpha = 1; |
CGContextSetFillPattern (myContext, myPattern, &alpha); |
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.
The code in Listing 6-5 contains a function that paints a colored pattern. The function incorporates all the steps discussed previously. A detailed explanation for each numbered line of code follows the listing.
Listing 6-5 A function that paints a colored pattern
void MyColoredPatternPainting (CGContextRef myContext, |
CGRect rect) |
{ |
CGPatternRef pattern;// 1 |
CGColorSpaceRef patternSpace;// 2 |
float alpha = 1,// 3 |
width, height;// 4 |
static const CGPatternCallbacks callbacks = {0, // 5 |
&MyDrawPattern, |
NULL}; |
CGContextSaveGState (myContext); |
patternSpace = CGColorSpaceCreatePattern (NULL);// 6 |
CGContextSetFillColorSpace (myContext, patternSpace);// 7 |
CGColorSpaceRelease (patternSpace);// 8 |
pattern = CGPatternCreate (NULL, // 9 |
CGRectMake (0, 0, H_PSIZE, V_PSIZE),// 10 |
CGAffineTransformMake (1, 0, 0, 1, 0, 0),// 11 |
H_PATTERN_SIZE, // 12 |
V_PATTERN_SIZE, // 13 |
kCGPatternTilingConstantSpacing,// 14 |
true, // 15 |
&callbacks);// 16 |
CGContextSetFillPattern (myContext, pattern, &alpha);// 17 |
CGPatternRelease (pattern);// 18 |
CGContextFillRect (myContext, rect);// 19 |
CGContextRestoreGState (myContext); |
} |
Here’s what the code does:
Declares storage for a CGPattern object that is created later.
Declares storage for a pattern color space that is created later.
Declares a variable for alpha and sets it to 1. This specifies the opacity of the pattern as completely opaque.
Declares variable to hold the height and width of the window. In this example, the pattern is painted over the area of a window.
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.
Creates a pattern color space object, setting the pattern’s base color space to NULL. When you paint a colored pattern, the pattern supplies its own color in the drawing callback, which is why you set the color space to NULL.
Sets the fill color space to the pattern color space object you just created.
Releases the pattern color space object.
Passes NULL because the pattern does not need any additional information passed to the drawing callback.
Passes a CGRect object that specifies the bounds of the pattern cell.
Passes a CGAffineTransform matrix that specifies how to translate the pattern space to the default user space of the context in which the pattern is used. This example passes the identity matrix.
Passes the horizontal pattern size as the horizontal displacement between the start of each cell. In this example, one cell will be painted adjacent to the next.
Passes the vertical pattern size as the vertical displacement between start of each cell.
Passes the constant kCGPatternTilingConstantSpacing to specify how Quartz should render the pattern. For more information, see “Tiling.”
Passes true for the isColored parameter, to specify that the pattern is a colored pattern.
Passes a pointer to the callbacks structure that contains version information, and a pointer to your drawing callback function.
Sets the fill pattern, passing the context, the CGPattern object you just created, and a pointer to the alpha value that specifies an opacity for Quartz to apply to the pattern.
Releases the CGPattern object.
Fills a rectangle that is the size of the window passed to the MyColoredPatternPainting routine. Quartz fills the rectangle using the pattern you just set up.
Last updated: 2007-12-11