A shadow is an image painted underneath, and offset from, a graphics object such that the shadow mimics the effect of a light source cast on the graphics object, as shown in Figure 7-1. Text can also be shadowed. Shadows can make an image appear three dimensional or as if it’s floating.
Shadows have three characteristics:
An x-offset, which specifies how far in the horizontal direction the shadow is offset from the image. Positive values indicate rightward displacement, and negative values indicate leftward displacement.
A y-offset, which specifies how far in the vertical direction the shadow is offset from the image. Positive values indicate upward displacement, and negative values indicate downward displacement.
A blur value, which specifies whether the image has a hard edge, as seen in the left side of Figure 7-2, or a diffuse edge, as seen in the right side of the figure.
This chapter describes how shadows work and shows how to use the Quartz 2D API to create them.
How Shadows Work
Painting With Shadows
Shadows in Quartz are part of the graphics state. You call the function CGContextSetShadow
, passing a graphics context, offset values, and a blur value. After shadowing is set, any object you draw has a shadow drawn with a black color that has a 1/3 alpha value in the DeviceRGB color space. In other words, the shadow is drawn using RGBA values set to {0, 0, 0, 1.0/3.0}
.
You can draw colored shadows by calling the function CGContextSetShadowWithColor
, passing a graphics context, offset values, a blur value, and a CGColor object. The values to supply for the color depend on the color space you want to draw in.
If you save the graphics state before you call CGContextSetShadow
or CGContextSetShadowWithColor
, you can turn off shadowing by restoring the graphics state. You also disable shadows by setting the shadow color to NULL
.
Follow these steps to paint with shadows:
Save the graphics state.
Call the function CGContextSetShadow
, passing the appropriate values.
Perform all the drawing to which you want to apply shadows.
Restore the graphics state
Follow these steps to paint with colored shadows:
Save the graphics state.
Create a CGColorSpace object to ensure that Quartz interprets the shadow color values correctly.
Create a CGColor object that specifies the shadow color you want to use.
Call the function CGContextSetShadowWithColor
, passing the appropriate values.
Perform all the drawing to which you want to apply shadows.
Restore the graphics state.
The two rectangles in Figure 7-3 are drawn with shadows—one with a colored shadow.
The function in Listing 7-1 shows how to set up shadows to draw the rectangles shown in Figure 7-3. A detailed explanation for each numbered line of code appears following the listing.
Listing 7-1 A function that sets up shadows
void MyDrawWithShadows (CGContextRef myContext, // 1 |
float wd, float ht); |
{ |
CGSize myShadowOffset = CGSizeMake (-15, 20);// 2 |
float myColorValues[] = {1, 0, 0, .6};// 3 |
CGColorRef myColor;// 4 |
CGColorSpaceRef myColorSpace;// 5 |
CGContextSaveGState(myContext);// 6 |
CGContextSetShadow (myContext, myShadowOffset, 5); // 7 |
// Your drawing code here// 8 |
CGContextSetRGBFillColor (myContext, 0, 1, 0, 1); |
CGContextFillRect (myContext, CGRectMake (wd/3 + 75, ht/2 , wd/4, ht/4)); |
myColorSpace = CGColorSpaceCreateDeviceRGB ();// 9 |
myColor = CGColorCreate (myColorSpace, myColorValues);// 10 |
CGContextSetShadowWithColor (myContext, myShadowOffset, 5, myColor);// 11 |
// Your drawing code here// 12 |
CGContextSetRGBFillColor (myContext, 0, 0, 1, 1); |
CGContextFillRect (myContext, CGRectMake (wd/3-75,ht/2-100,wd/4,ht/4)); |
CGColorRelease (myColor);// 13 |
CGColorSpaceRelease (myColorSpace); // 14 |
CGContextRestoreGState(myContext);// 15 |
} |
Here’s what the code does:
Takes three parameters—a graphics context and a width and height to use when constructing the rectangles.
Declares and creates a CGSize object that contains offset values for the shadow. These values specify a shadow offset 15 units to the left of the object and 20 units above the object.
Declares an array of color values. This example uses RGBA, but these values won’t take on any meaning until they are passed to Quartz along with a color space, which is necessary for Quartz to interpret the values correctly.
Declares storage for a color reference.
Declares storage for a color space reference.
Saves the current graphics state so that you can restore it later.
Sets a shadow to have the previously declared offset values and a blur value of 5, which indicates a soft shadow edge. The shadow will appear gray, having an RGBA value of {0, 0, 0, 1/3}.
The next two lines of code draw the rectangle on the right side of Figure 7-3. You replace these lines with your own drawing code.
Creates a DeviceRGB color space. You need to supply a color space when you create a CGColor object.
Creates a CGColor object, supplying the DeviceRGB color space and the RGBA values declared previously. This object specifies the shadow color, which in this case is red with an alpha value of 0.6.
Sets up a color shadow, supplying the red color you just created. The shadow uses the offset created previously and a blur value of 5, which indicates a soft shadow edge.
The next two lines of code draw the rectangle on the left side of Figure 7-3. You replace these lines with your own drawing code.
Releases the color object because it is no longer needed.
Releases the color space object because it is no longer needed.
Restores the graphics state to what it was prior to setting up the shadows.
© 2001, 2007 Apple Inc. All Rights Reserved. (Last updated: 2007-12-11)