3
votes

My blog has been mentioned here before as an answer to questions. I can't link to one of them, because this form claims I'm a spammer. Sigh. Anyway, now I want to write the definitive blog post on drawing rotated text, so it can also be used for answers here (heh). Here is my first try:

http://www.platinumball.net/blog/2009/06/01/drawing-nsstrings-in-unusual-rotations/

That works well, it does everything I want, except for the fact that it uses CGContextSelectFont(), which limits text output to MacRoman. That is Teh Sukk.

I've been searching for an answer to this problem for almost a year now, including searching this site several times, without success. I've seen examples that seem close to what I want, but apparently I'm too stupid to bend them to my will. I'm including the main method from the NSString category I wrote, which shows the guts of what I'm doing. If you need to see the rest of the code, you can download it from the link to my blog I gave above. Thanks ...

-(void)drawAtPoint:(CGPoint)point withFont:(UIFont*)font
 orientation:(WBOrientation)orient
{
    CGContextRef       ctxt = [self contextSave];
    const std::string  tbuf = toStdString(self, NSMacOSRomanStringEncoding);
    CGAffineTransform  tran = CGAffineTransformMake(1, 0, 0, -1, 0, 0);

    switch (orient)
    {
        case WBOrientUp:
        // nothing to do
        break;

        case WBOrientDown:
        tran = CGAffineTransformRotate(tran, degreesToRadians(180.0));
        break;

        case WBOrientLeft:
        tran = CGAffineTransformRotate(tran, degreesToRadians(90.0));
        break;

        case WBOrientRight:
        tran = CGAffineTransformRotate(tran, degreesToRadians(-90.0));
        break;

        default:
        assert(false);
        break;
    }

    contextFont(ctxt, font);
    CGContextSetTextDrawingMode(ctxt, kCGTextFill);
    CGContextSetTextMatrix(ctxt, tran);
    CGContextSetTextPosition(ctxt, point.x, point.y);
    CGContextShowText(ctxt, tbuf.c_str(), tbuf.length());

    [self contextRestore:ctxt];
}
2
Allen: skimmed your blog post. You say that you need const char * s and have a hard time getting them. NSString has a method -cStringUsingEncoding: that seems to do what you need directly (see docs for memory management around it). Just FYI.Ben Zotto

2 Answers

1
votes

only a few days after i did it myself =)

this is how i solved it:

view.layer.transform = CATransform3DRotate(view.layer.transform, 3.1415, 0,0,1); // this is for 180 degrees.
1
votes

Set the CGContext as the current graphics context using the UIGraphicsPushContext function, then draw the string using UIKit, then pop the context back off the stack using the UIGraphicsPopContext function.

The AppKit (Mac) solution is essentially the same, using NSGraphicsContext for step 1 and AppKit's NSString additions for step 2. For window contexts in -[NSView drawRect:], step 3 goes away (you would obtain the CGContext from the NSGraphicsPort in step 1, meaning it's already set); for other contexts, such as bitmap or PDF contexts, you would use the same NSGraphicsPort method (setCurrentContext:) in both step 1 and step 3.