What's the CoreText equivalent to AppKit's NSObliquenessAttributeName?
Asked Answered
M

3

5

I'm drawing some text in Mac/iOS cross-platform code using CoreText. I may be using fonts that do not have a real "Italic" version installed in the OS for all users, but they need to be aware that the text is italic even then.

With AppKit's NSAttributedString -drawAtPoint:, I can use NSObliquenessAttributeName to make the text slanted (and thus look italic -- well, oblique). CoreText doesn't seem to have an equivalent for this attribute. At least I found none in CTStringAttributes.h (not that there's any documentation even years after CoreText was released).

Does anyone know how I can get oblique text with CoreText on iOS?

Mayest answered 28/2, 2012 at 17:26 Comment(3)
Documentation for Core Text? You mean this? developer.apple.com/library/ios/documentation/Carbon/Reference/…Presumably
I clicked "Reference" in Mac dev center, typed CoreText into the search field, and all I got was three sample apps. How'd you pull out these secret docs?Mayest
It's the top Reference hit on developer.apple.com/library/mac/search/?q=core+text .Presumably
B
1

Displaying a font that has no italic trait as italic is generally a bad idea. However, I can understand that there are some cases where this has to be enforced anyways.

The only solution that comes to my mind right now is to create a custom font with a sheared font matrix:

CGAffineTransform matrix = CGAffineTransformMake(1, tan(degreesToRadians(0)), tan(degreesToRadians(20)), 1, 0, 0);  
CTFontRef myfont = CTFontCreateWithName(CFSTR("Helvetica"), 48, &matrix);

You'll have to play with the matrix and see what brings the best results. (Please not that this is a fake code mix out of my head and the internet.)

Brouwer answered 28/2, 2012 at 17:45 Comment(6)
I think you want a shear matrix rather than a rotation matrix.Deglutition
Thanks, I'll try that, with Alastair's correction. I'd be happy not to have to display faux italics, but it's pre-existing data that used to do this, and I can't just drop information that used to display just fine previously. :-)Mayest
Yes, a slant matrix is what you'd want.Brouwer
Another workaround would be to fall back to a different font that does have italics. But that would probably look even worse...Recliner
Looking at this again, I note that Max’s matrix actually is a shear matrix (and not a rotation matrix as he originally said).Deglutition
I've fixed the text. now it's sheared :)Brouwer
D
9

I’d try using the affine transform argument to CTFontCreateWithName() with a shear matrix. For instance

CGAffineTransform matrix = { 1, 0, 0.5, 1, 0, 0 };
CTFontRef myFont = CTFontCreateWithName(CFSTR("Helvetica"), 48, &matrix);

That will create quite an extreme skew (assuming I got it right), but you get the idea.

Update:

In fact, the documentation appears to imply that this is the right way to do things.

Deglutition answered 28/2, 2012 at 17:54 Comment(1)
Good answer but please never make me have to look at this.Projection
T
1

Haven't tried, but according to iOS Programming Pushing The Limits, passing kCTFontItalicTrait to CTFontCreateCopyWithSymbolicTraits will choose true italic if available, and oblique otherwise. There's also kCTFontSlantTrait for manual decimal slant up to 30 degrees.

Threescore answered 28/2, 2012 at 17:35 Comment(2)
As far as I know this only works for fonts that actually feature a italic variant. I understood the question as if the OP wanted to display italic with a font that does not have italic.Brouwer
I tried kCTFontSlantTrait, that didn't help (I get the feeling that's a read-only attribute). The italic trait picks an oblique font in cases like Courier, that actually come with a pre-built oblique variant, but some of the fonts I need to display don't even have that.Mayest
B
1

Displaying a font that has no italic trait as italic is generally a bad idea. However, I can understand that there are some cases where this has to be enforced anyways.

The only solution that comes to my mind right now is to create a custom font with a sheared font matrix:

CGAffineTransform matrix = CGAffineTransformMake(1, tan(degreesToRadians(0)), tan(degreesToRadians(20)), 1, 0, 0);  
CTFontRef myfont = CTFontCreateWithName(CFSTR("Helvetica"), 48, &matrix);

You'll have to play with the matrix and see what brings the best results. (Please not that this is a fake code mix out of my head and the internet.)

Brouwer answered 28/2, 2012 at 17:45 Comment(6)
I think you want a shear matrix rather than a rotation matrix.Deglutition
Thanks, I'll try that, with Alastair's correction. I'd be happy not to have to display faux italics, but it's pre-existing data that used to do this, and I can't just drop information that used to display just fine previously. :-)Mayest
Yes, a slant matrix is what you'd want.Brouwer
Another workaround would be to fall back to a different font that does have italics. But that would probably look even worse...Recliner
Looking at this again, I note that Max’s matrix actually is a shear matrix (and not a rotation matrix as he originally said).Deglutition
I've fixed the text. now it's sheared :)Brouwer

© 2022 - 2024 — McMap. All rights reserved.