0

Something strange is going on. I was working with NSAttributedString for some formatting, including slants and skews. NSObliquenessAttributeName did the trick. But then I wanted to expand into CoreText to take control of the frame the text is actually rendered in. Even before figuring it all out, I notice my NSObliquenessAttributeName is not being rendered. All my other attributes are still rendered so I'm a bit confused.

- (void)drawSlanted
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSaveGState(context);

    [[UIColor blackColor] setFill];

    NSAttributedString *text = [[NSAttributedString alloc] initWithString:@"This isn't slanted... but is stroked" attributes:@{NSObliquenessAttributeName: @10.0,
                                                                                                                               NSStrokeWidthAttributeName: @2.0}];

    // Flip Coordinates
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0.0, CGRectGetHeight(self.bounds));
    CGContextScaleCTM(context, 1.0, -1.0);

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)text);
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, text.length), [UIBezierPath bezierPathWithRect:self.bounds].CGPath, NULL);

    CTFrameDraw(frame, context);

    CFRelease(frame);

    CGContextRestoreGState(context);
}
Ryan Poolos
  • 18,421
  • 4
  • 65
  • 98

1 Answers1

2

In some sense, NSAttributedString supports arbitrary attributes. That is, you can put any attribute key-value pair you like in an attributes dictionary and NSAttributedString will dutifully store it for you. That includes attributes you make up.

However, NSAttributedString will not make use of attributes it doesn't understand to format or lay out the string. It only understands Cocoa's predefined attributes.

The same is true of Core Text. It only understands certain attributes. Unfortunately, the set of attributes that Core Text understands is not the same as the set that Cocoa and NSAttributedString understand. The set that Core Text understands is documented in the Core Text String Attributes Reference. It doesn't include an obliqueness attribute.

I'm not sure, but I think you need to use a font created with a transformation matrix to get oblique glyphs. (Of course, you should prefer proper italics unless you have a reason not to.)

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • Very helpful info. That was what I was worried about, but couldn't find good documentation to support it other than header files missing the attributes I had working previously lol. – Ryan Poolos Oct 21 '14 at 14:34
  • That being said, I do need to use skews over italics, this is for a text editor of sorts so the slant needs to be in the control of a designer. I'll look into generating fonts. I've see some code for that previously to do other unique things with the transform matrix. – Ryan Poolos Oct 21 '14 at 14:35
  • With that in mind, do you have any knowledge of that? Sample code, etc. – Ryan Poolos Oct 21 '14 at 14:35
  • It occurs to me that you're already using `CGContextSetTextMatrix()` but you're supplying the identity matrix. If you just apply a skew matrix, that will achieve the slant you want. You can use `CGAffineTransformMake(1, 0, skew, 1, 0, 0)`, where `skew` is the distance to the right that pixels should be shifted as the `y` increases. That's basically, `tan(angleInRadians)`. – Ken Thomases Oct 22 '14 at 02:19
  • Dude you're the man. That totally worked. I thought I was going to have to move to drawing the glyphs individually. I was worried the matrix transformed would do all of it as a whole which would breakdown for multiple lines in a block. Thanks a ton. – Ryan Poolos Oct 22 '14 at 02:44