When converting text to image, the converted images were different between macOS and iOS. The main differences are font weight and line height.
Font Weight
Thought the font weight and the fonts are the same, on macOS the font result is always thicker. I don't know why. But in my experience, if you use "HelveticaNeue-Light" for iOS, use "HelveticaNeue-Thin" for macOS.
Line Height
The line height of font is even tricky.
Equation
In Apple's doc, Apple gives below graph. We could draw a simple equation from the graph.
line height = ascent + decent + line gap (leading)
So I did two tests on both iOS and macOS in Playgound.
// macOS
func getFontInfo(_ name:String) {
let font = NSFont(name: name, size: 17.0)!
print(font.ascender) // 13.09033203125
print(font.descender) // -3.90966796875
print(font.leading) // 0.0
print(font.ascender - font.descender + font.leading) // 17.0
let layoutManager = NSLayoutManager()
print(layoutManager.defaultLineHeight(for: font)) // 20.0
}
getFontInfo("Helvetica")
// iOS
func getFontInfo(_ name:String) {
let font = UIFont(name: name, size: 17.0)!
print(font.ascender) // 15.64033203125
print(font.descender) // -3.90966796875
print(font.leading) // 0.0
print(font.ascender - font.descender + font.leading) // 19.55
print(font.lineHeight) // // 19.55
}
getFontInfo("Helvetica")
From the two tests, we could draw two conclusions:
- The equation on iOS was balanced, but on macOS was not.
- For the same font with the same weight, the
ascender
were different.
I didn't know why those happened. So I sent an "Apple Developer Technical Support". Here was the reply from Apple.
According to Apple, if I wanted to use the equation, I should use Core Text
framework. But in fact Apple didn't provide line height in Core Text
.
Then I did another two tests.
// macOS
func getLineHeightForFontName(_ name:String) {
let font = CTFontCreateWithName(name as CFString, 17.0, nil)
print(CTFontGetAscent(font)) // 13.09033203125
print(CTFontGetDescent(font)) // 3.90966796875
print(CTFontGetLeading(font)) // 0.0
}
getLineHeightForFontName("Helvetica")
// iOS
func getLineHeightForFontName(_ name:String) {
let font = CTFontCreateWithName(name as CFString, 17.0, nil)
print(CTFontGetAscent(font)) // 13.09033203125
print(CTFontGetDescent(font)) // 3.90966796875
print(CTFontGetLeading(font)) // 0.0
}
getLineHeightForFontName("Helvetica")
From all four tests, we could get the conclusions:
- Though on iOS, the equation was balanced. The ascent property was modified by Apple.
- On macOS, the line height was modified by Apple.
- From the above two conclusions, both NSFont and UIFont were not trusted. The only trusted line height was something we get from
Core Text
.
Line Height
#if os(macOS)
func getLineHeight(_ font:NSFont) -> CGFloat {
let ctFont = CTFontCreateWithName(font.fontName as CFString, font.pointSize, nil)
return CTFontGetAscent(ctFont) + CTFontGetDescent(ctFont) + CTFontGetLeading(ctFont)
}
#else
func getLineHeight(_ font:UIFont) -> CGFloat {
let ctFont = CTFontCreateWithName(font.fontName as CFString, font.pointSize, nil)
return CTFontGetAscent(ctFont) + CTFontGetDescent(ctFont) + CTFontGetLeading(ctFont)
}
#endif