Giter Site home page Giter Site logo

vfont's Introduction

Version Platforms SwiftUI Swift Package Manager Cocoapods

VFont

VFont is a brilliant library which simplifies working with variable fonts in iOS projects.

If you've never heard about variable fonts, I'd recommend reading this article Variable fonts in real life: how to use and love them by @romashamin

Sponsored by Evil Martians

What does the library make easier?

First of all, I wondered if variable fonts are supported in iOS. Nowadays, developers use the top-level UIFont class to work individually with Light, Regular, Medium, Bold, and other font styles. I discovered that VF support had already been added in iOS 3.2. However, it was implemented using low level code in the CTFont class in the CoreText library. This leads to extra work in order to get to variable fonts using CoreText and UIFont.

Usage

First, you need to add the custom variable font to your project. If you've never done this, I recommend reading this tutorial.

โ—๏ธ Be aware that the font file name can be different from the actual font name! To get the correct full font name, upload the font file to fontgauntlet.com.

Native instruments

// First, you have to get information about the variable font (axes names, IDs, and allowed values). But the current axis value isn't there ๐Ÿคทโ€โ™‚๏ธ
// Here you can face a problem, like the custom font wasn't added to the project, was added incorrectly, or font name isn't correct
let uiFont = UIFont(name: "Martian Mono", size: 16.0)!
let ctFont = CTFontCreateWithName(uiFont.fontName as CFString, 16.0, nil)
let variationAxes = CTFontCopyVariationAxes(ctFont) as! [Any] // font information with weird format ๐Ÿ‘Ž

// To set new values you need to know the correct axis IDs and allowed values (maxValue and minValue)
let variations = [2003265652: 600, 2003072104: 100] // 2003265652 - 'Weight'; 2003072104 - `Width`

// As we know, text elements in UIKit use the UIFont class. So, you have to create new UIFont object with new values for axes
let uiFontDescriptor = UIFontDescriptor(fontAttributes: [.name: uiFont.fontName, kCTFontVariationAttribute as UIFontDescriptor.AttributeName: variations])
let newUIFont = UIFont(descriptor: uiFontDescriptor, size: uiFont.pointSize) 
// Now, you can apply the UIFont object for UI text elements
// Here you may notice the name of the new UIFont object has been changed to 'MartianMono-Regular_wght2580000_wdth640000'
let label = UILabel()
label.font = newUIFont

If you want to continue changing the current font object, or if you'd like to create more complex logic, you need to store the UIFont object. Moreover, you should parse the variation axes values and store these, too. But don't worry, VFont will do this for you!

VFont library

UIKit

import VFont

let vFont = VFont(name: "Martian Mono", size: 16)! // UIFont like initialization
vFont.setValue(400, forAxisID: 2003265652) // setting a new value for the 'Weight' axis

let label = UILabel()
label.font = vFont.uiFont // apply the variable font for a UI text element
vFont.getAxesDescription() // get the font information with ะฐ human readable format, if you need it โœ…

// override the `updated` closure to observe all font changes, if you're going to change it at runtime
vFont.updated = { uiFont in
    label.font = uiFont
}

SwiftUI

struct ContentView: View {

    var body: some View {
       Text("Title 1")
          .font(.vFont("Martian Mono", size: 16, axisID: 2003265652, value: 450))
       Text("Title 2")
           .font(.vFont("Inter", size: 32, axes: [2003072104: 80, 2003265652: 490])
    }
    
}

Why do we use number IDs instead of axis names? Good question! But the answer is really simple. The CTFont framework which works with variable fonts under the hood returns different axis names for different system languages. This means that only the axis number IDs are unique values. If you find a way of receiving English names regardless of system language, I would appreciate knowing about this!

Installation

Swift Package Manager

  • File > Swift Packages > Add Package Dependency
  • Search https://github.com/dufflink/vfont
  • Select Up to Next Major with 0.6.1

Cocoapods

To integrate VFont to your Xcode project using CocoaPods, specify it in your Podfile:

pod 'VFont'

Advanced usage

If you use UIKit, you can create your own font class inheriting the VFont class!

UIKit

import VFont

final class MartianMono: VFont {
    
    init?(size: CGFloat) {
        super.init(name: "Martian Mono", size: size)
    }
    
    var weight: CGFloat {
        get {
            return axes[2003265652]?.value ?? .zero
        } set {
            setValue(newValue, axisID: 2003265652)
        }
    }
    
    var width: CGFloat {
        get {
            return axes[2003072104]?.value ?? .zero
        } set {
            setValue(newValue, axisID: 2003072104)
        }
    }
    
}
let font = MartianMono(size: 16)
        
font?.weight = 300
font?.width = 90

SwiftUI

In a SwiftUI project you can create static method as a Font structure extension:

extension Font {
    
    static func martianMono(size: CGFloat, width: CGFloat = 0, weight: CGFloat = 0) -> Font {
        return .vFont("Martian Mono", size: size, axes: [
            2003072104: width,
            2003265652: weight
        ])
    }
    
}
struct ContentView: View {
    
    var body: some View {
        Text("Hello, world!")
            .font(.martianMono(size: 16, width: 300, weight: 100))
    }
    
}

Examples

Move on to Examples and research how does it work! Also, you can lanch the examples in Xcode. To complete this, clone the repository and launch the VFont.xcworkspace file.

vfont-uikit-demo.mp4

Roadmap

  • The next step is creating a script that will parse the Info.plist file and which will automatically generate the font classes for UIKit and the extensions for SwiftUI. The generated code will have the same structure as in the Font class section abowe.

  • Support for tvOS, watchOS, and macOS

License

VFont is released under the MIT license. See LICENSE for details.

vfont's People

Contributors

dufflink avatar travis-turner avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

vfont's Issues

Couldn't parse the NSCTVariationAxisFlags font attribute

I get this print-log a lot (I have a lot of texts in my apps). I guess its related to the fonts I use do not support some variations such as width. Is this print really needed. Or can it at least be optional?

Couldn't parse the NSCTVariationAxisFlags font attribute

Cannot find type 'Font' in scope

I get the following errror when exporting my app:

Cannot find type 'Font' in scope

On this row:

public extension Font {

in VFont.swift

Any ideas?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.