Search code examples
swiftuifontuifontdescriptor

Creating an italic version from a *light* font using symbolic traits


I'd like to get an italic version of a light font, for example "HelveticaNeue-Light".

Using a fontDescriptor gives me the italic version of the 'regular' "Helvetica Neue" instead of the italic "HelveticaNeue-Light". I could retrieve the fontDescriptor.fontAttributes and update the UIFontDescriptor.AttributeName.name, but that's tricky, because the naming is different per font ("HelveticaNeue" uses "Italic", Helvetica uses "Oblique").

let lightFont = UIFont(name: "HelveticaNeue-Light", size: 16.0)!
var lightFontDescriptor = lightFont.fontDescriptor.withSymbolicTraits([.traitItalic])!
var lightFontWithItalicTraits = UIFont(descriptor: lightFontDescriptor, size: 0)

// <UICTFont: ..> font-family: "HelveticaNeue-Light"; font-weight: normal; font-style: normal; font-size: 16.00pt
print(lightFont)

// <UICTFont: ..> font-family: "Helvetica Neue"; font-weight: normal; font-style: italic; font-size: 16.00pt
print(lightFontWithItalicTraits)

// The font I expect:
let lightItalicFont = UIFont(name: "HelveticaNeue-LightItalic", size: 16.0)!
// <UICTFont: ..> font-family: "HelveticaNeue-LightItalic"; font-weight: normal; font-style: italic; font-size: 16.00pt
print(lightItalicFont)

Any other idea how to get the italic version of an existing font?


Solution

  • It's not the prettiest, but it's functional. It handles all built-in iOS fonts.

    Extension:

    extension UIFont {
        func italic() -> UIFont? {
            if let italic = UIFont.init(name: "\(self.fontName)-Italic", size: self.pointSize) {
                return italic
            } else if let italic = UIFont.init(name: "\(self.fontName)Italic", size: self.pointSize) {
                return italic
            }
            if let oblique = UIFont.init(name: "\(self.fontName)-Oblique", size: self.pointSize) {
                return oblique
            } else if let oblique = UIFont.init(name: "\(self.fontName)Oblique", size: self.pointSize) {
                return oblique
            }
            var suffixFontName = self.fontName // for font names that have a 2 letter suffix such as ArialMT
            suffixFontName.removeLast(2)
            let suffix = self.fontName.suffix(2)
            if let suffixFontName = UIFont.init(name: "\(suffixFontName)-Italic\(suffix)", size: self.pointSize) {
                return suffixFontName
            }
            if let suffixFontName = UIFont.init(name: "\(suffixFontName)Italic\(suffix)", size: self.pointSize) {
                return suffixFontName
            }
            // no italic, oblique, or mt italic font found
            return nil
        }
    }
    

    Usage:

        let helveticaNeueLightItalic = UIFont(name: "HelveticaNeue-Light", size: 16.0)!.italic()
        print(helveticaNeueLightItalic)
    
        let helveticaItalic = UIFont(name: "Helvetica", size: 16.0)!.italic()
        print(helveticaItalic)
    
        let helveticaLightItalic = UIFont(name: "Helvetica-Light", size: 16.0)!.italic()
        print(helveticaLightItalic)
    
        let arialMtItalic = UIFont(name: "ArialMT", size: 16.0)!.italic()
        print(arialMtItalic)
    
        let arialMtBoldItalic = UIFont(name: "Arial-BoldMT", size: 16.0)!.italic()
        print(arialMtBoldItalic)