3
votes

I'm tying to draw two different shadows on some text to create an embossed effect. Here's the portion of my drawInRect where I draw the text with the first shadow (all the variables used are already defined):

CGContextSetShadowWithColor(context, textInnerShadowOffset, textInnerShadowBlurRadius, textInnerShadowColor.CGColor);
[textColor setFill];
[self.text drawInRect:rect withFont:self.font lineBreakMode:self.lineBreakMode alignment:self.textAlignment];

But now I'm faced with the problem of drawing the second shadow. I assume I'll need to change the shadow and draw the text again, but I need to do so without adding another copy of the text.

How can I draw text without really drawing the text itself? Changing the fill color to clearColor doesn't work. I've seen people use clipping masks for this, but AFAICT that will only work for simple shapes, not text.

Alternatively, is there an easier way to draw two shadows on the same text?

1

1 Answers

1
votes

Two options, depending on the exact effect you want:

  • If you want the first, "upper" shadow to also contribute to the second, "lower" shadow underneath it, use a transparency layer.

    1. Set your CGContext's shadow for the "lower" shadow
    2. Create a transparency layer using CGContextBeginTransparencyLayer
    3. Set the context's shadow for the "upper" shadow
    4. Draw your text
    5. End the transparency layer using CGContextEndTransparencyLayer

(Note that transparency layers can be quite expensive. It's best to call CGContextBeginTransparencyLayerWithRect and pass in as small a rect as you can.)

  • If you want the shadows to be independent -- the only thing that contributes to each shadow is the text -- you'll need to use a trick.

Set up the shadow with an additional large offset, big enough so that you can draw the text outside of the bounds of your context and have the shadow land in the correct place. That way you'll see only the shadow, but not the text.

text and shadow with large offset

  1. Figure out what offset is "big enough". It will probably depend on the size of the context you're drawing into (based on your view), and maybe the bounds of the text. Or, just fudge it: pick an absurdly large value like 5000 pt.
  2. Set up your shadow. Add the big offset to its normal y offset.
  3. Draw the text, offset vertically by the big offset.

Repeat 1-3 for each "lower" shadow, from back to front. Afterwards, draw the text and the "uppermost" shadow last, without the offset.