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?

uliwitness
  • 8,532
  • 36
  • 58
  • Documentation for Core Text? You mean this? https://developer.apple.com/library/ios/documentation/Carbon/Reference/CoreText_Framework_Ref/ – Peter Hosey Feb 28 '12 at 17:34
  • 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? – uliwitness Feb 28 '12 at 18:09
  • It's the top Reference hit on https://developer.apple.com/library/mac/search/?q=core+text . – Peter Hosey Feb 28 '12 at 18:29

3 Answers3

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.

al45tair
  • 4,405
  • 23
  • 30
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.

Sören Kuklau
  • 19,454
  • 7
  • 52
  • 86
  • 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. – Max Seelemann Feb 28 '12 at 17:42
  • 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. – uliwitness Feb 28 '12 at 17:51
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.)

Max Seelemann
  • 9,344
  • 4
  • 34
  • 40
  • 1
    I think you want a shear matrix rather than a rotation matrix. – al45tair Feb 28 '12 at 17:54
  • 1
    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. :-) – uliwitness Feb 28 '12 at 18:03
  • 1
    Yes, a slant matrix is what you'd want. – Max Seelemann Feb 28 '12 at 18:11
  • Another workaround would be to fall back to a different font that does have italics. But that would probably look even worse... – fzwo Feb 28 '12 at 22:38
  • Looking at this again, I note that Max’s matrix actually *is* a shear matrix (and not a rotation matrix as he originally said). – al45tair Feb 29 '12 at 10:52
  • I've fixed the text. now it's sheared :) – Max Seelemann Feb 29 '12 at 11:17