Search code examples
iosuiimagecore-graphicscore-animation

Create a UIImage after skewing text


I'm trying to create a UIImage from an NSAttributedString that's has a skewed transform. I can make a UILabel or UIImageView and skew that view, but unfortunately I need to create a UIImage after the string has been skewed. I've tried the following..

CGAffineTransform skewTransform = CGAffineTransformIdentity;
skewTransform.b = (M_1_PI / 2);

UIGraphicsBeginImageContextWithOptions(mSize, NO, 1.0);
UILabel* skewedLabel = [[UILabel alloc] init];
skewedLabel.attributedText = stringToBeSkewed;
CGContextSetTextMatrix(UIGraphicsGetCurrentContext(), skewTransform); 
skewedLabel.layer.affineTransform = skewTransform;

//    The following 3 calls haven't worked
//    [stringToBeSkewed drawInRect:inputRectParam.rect];
//    [skewedLabel.layer renderInContext:UIGraphicsGetCurrentContext()];
//    [skewedLabel.layer drawInContext:UIGraphicsGetCurrentContext()];

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

I get that the CALayer is CoreAnimation and CoreGraphics doesn't recognize this, but is there a way to get skewed text to be captured within the context and converted into a UIImage?


Solution

  • I was able to get a UIImage from text by doing the following, hope this helps someone out. Also, it's not the cleanest image, so any advice on sharpening it up would be appreciated.

    UIFont* font = [UIFont fontWithName:@"(your font name)" size:60];
    CTFontRef skewFont = CTFontCreateWithName((__bridge CFStringRef)font.fontName, font.pointSize, NULL);
    
    // Create an attributed string for shadowed text
    CFStringRef skewKeys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName };
    CFTypeRef skewValues[] = { skewFont, [UIColor colorWithRed:0 green:0 blue:0 alpha:.4].CGColor };
    CFDictionaryRef skewAttributes = CFDictionaryCreate(NULL, (const void **)&skewKeys, (const void **)&skewValues,
                                              sizeof(skewKeys) / sizeof(skewKeys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    CFStringRef theCFString = (__bridge CFStringRef)inputStringParam.string;
    CFAttributedStringRef skewString = CFAttributedStringCreate(NULL, theCFString, skewAttributes);
    CFRelease(skewAttributes);
    
    
    // create skew transform
    CGAffineTransform skewTransform = CGAffineTransformIdentity;
    skewTransform.b = (value to be skewed);
    
    // Draw the string
    CTLineRef skewLine = CTLineCreateWithAttributedString(skewString);
    
    CGContextSetTextMatrix(UIGraphicsGetCurrentContext(), CGAffineTransformMakeScale(1.0, -1.0));
    CGContextConcatCTM(UIGraphicsGetCurrentContext(), skewTransform);
    
    // draw and capture shadow image
    CGContextSetTextPosition(UIGraphicsGetCurrentContext(), inputDrawPointParam.point.x, inputDrawPointParam.point.y);
    CTLineDraw(skewLine, UIGraphicsGetCurrentContext());
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    CFRelease(skewLine);
    CFRelease(skewString);
    CFRelease(skewFont);