iphonequartz-graphics

Drawing rotated text with NSString drawInRect


I found this answer on how to draw rotated text with NSString drawInRect:, but I'm not sure how it works since it only sort of works for me: https://discussions.apple.com/thread/1779814?start=0&tstart=0

My code looks like:

           CGContextSaveGState(context);
           CGContextDrawLinearGradient(context, gradient, CGPointMake(0, centY - halfWidth), CGPointMake(0, centY + halfWidth), 0);

            // Add text                
            CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); 
            NSString *str = @"some test string";

            CGAffineTransform transform1 = CGAffineTransformMakeRotation(M_PI/4);

            CGContextConcatCTM(context, transform1);
            CGContextTranslateCTM(context, 0, 0);
            UIFont *font = [UIFont systemFontOfSize:16.0];

            [str drawInRect:CGRectMake(0, 0, 200, 100) withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UIBaselineAdjustmentNone];

So when I use this, I see text being drawn 45 degrees below the x-axis. I want to draw the text vertically along my lineargradient. So I thought I could do that by using M_PI/2 for 90 degrees. I do not see my text though. I have tried different transforms for the rotation, and only some seem to work like M_PI/4 and M_PI/8. I would think that if I used -M_PI/4 it would have the text 45 degrees above the x-axis and M_PI/2 would be 90 degrees below the x-axis. But both turn up with nothing.

Any thoughts? thanks.


Solution

  • I think what's happening is that you're rotating the text to a location outside of the view because it rotates the context by pivoting on the origin.

    After your rotation you need to do a translation to move the context back into the view. In the example below, I rotate the context counterclockwise 90 degrees. Then I translate the tx of the context the distance of the height.

    - (void)drawRect:(CGRect)rect
    {
        CGContextRef context = UIGraphicsGetCurrentContext(); 
    
        CGContextSaveGState(context);
    
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
        // Create the gradient 
        CGColorRef startColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0].CGColor; 
        CGColorRef endColor = [UIColor colorWithRed:200.0/255.0 green:200.0/255.0 blue:200.0/255.0 alpha:1.0].CGColor;
        NSArray *colors = [NSArray arrayWithObjects:(id)startColor, (id)endColor, nil];
        CGFloat locations[] = { 0.0, 1.0 };
        CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef) colors, locations);
        CGContextDrawLinearGradient(context, gradient, CGPointMake(rect.origin.x + rect.size.width / 2, rect.origin.y), CGPointMake(rect.origin.x + rect.size.width / 2, rect.origin.y + rect.size.height), 0);
    
        // Create text              
        CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor); 
        NSString *string = @"some test string";
        UIFont *font = [UIFont systemFontOfSize:16.0];
    
        // Rotate the context 90 degrees (convert to radians)
        CGAffineTransform transform1 = CGAffineTransformMakeRotation(-M_PI_2);
        CGContextConcatCTM(context, transform1); 
    
        // Move the context back into the view 
        CGContextTranslateCTM(context, -rect.size.height, 0);
    
        // Draw the string 
        [string drawInRect:rect withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentLeft];
    
        // Clean up 
        CGGradientRelease(gradient);
        CGColorSpaceRelease(colorSpace);
    
        CGContextRestoreGState(context);
    }
    

    Note that you can also get the size of how the string will be rendered, which can help in doing calculations for the alignment of the text.

        CGSize stringSize = [string sizeWithFont:font];