-
Notifications
You must be signed in to change notification settings - Fork 126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add registerFont
to Apple platforms
#598
Merged
Alex009
merged 7 commits into
icerockdev:develop
from
darronschall:ios-font-resource-register-font
Apr 18, 2024
Merged
Add registerFont
to Apple platforms
#598
Alex009
merged 7 commits into
icerockdev:develop
from
darronschall:ios-font-resource-register-font
Apr 18, 2024
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
darronschall
force-pushed
the
ios-font-resource-register-font
branch
from
November 15, 2023 17:22
74acb81
to
a6e6222
Compare
This makes the macOS `FontResource` consistent with the iOS `FontResource`.
The `FontResource` code is the same on both iOS and macOS, except for the helper to create either a `UIFont` or an `NSFont`. Move those helpers to platform-specific code, while keeping the common code shared for easier maintenance. This follows the same approach that we use for `ColorResource`.
Kotlin/Native can't throw an `NSError::class`. So, we make an `NSErrorException` wrapper that is `Throwable` that contains the underlying `NSError`. This helps us propagate `NSError`s to calling code. Callers an inspect the underlying error, instead of being stuck with just a `KotlinException`. In your Swift code, use this `Error` extension to make it easy to inspect the underlying error: ``` extension Error { var wrappedNSError: NSError? { let kotlinException = (self as NSError).userInfo["KotlinException"] as? KotlinException let nsErrorException = kotlinException as? NSErrorException return nsErrorException?.nsError as? NSError } } ``` Example usage: ``` do { try kotlinMethodThatThrowsNSErrorException() } catch { if let wrappedError = error.wrappedNSError { print("wrappedError domain: \(wrappedError.domain)") print("wrappedError code: \(wrappedError.code)") print("wrappedError userInfo: \(wrappedError.userInfo)") } } ```
This uses `CTFontManagerRegisterGraphicsFont` in order to register the font with the font manager. See: https://developer.apple.com/documentation/coretext/1499499-ctfontmanagerregistergraphicsfon Calling this method during application startup fixes an issue in SwiftUI where the `.fontWeight` call would fail to find the correct font. In the event this method fails and throws, see https://developer.apple.com/documentation/coretext/ctfontmanagererror for the list of possible error codes.
The documentation for `CTFontManagerRegisterGraphicsFont` at https://developer.apple.com/documentation/coretext/1499499-ctfontmanagerregistergraphicsfon hints that we should use `CTFontManagerRegisterFontsForURL` instead (since our fonts are backed by files in our bundle): > Fonts that are backed by files should be registered using CTFontManagerRegisterFontsForURL(_:_:_:).
Instead of allocating the `CGFontRef` during initialization, delay until first use. This is helpful for scenarios that use `registerFont` to add the font to the Font Manager and then access the font by name. In this situation, bypassing the `uiFont` or `nsFont` helpers, the `fontRef` is never accessed.
Follow "The Create Rule" for Core Foundation functions per https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html#//apple_ref/doc/uid/20001148-103029 We keep the `CGFontRef` around that we created, but the interim data structures along the way can be released.
darronschall
force-pushed
the
ios-font-resource-register-font
branch
from
February 22, 2024 21:02
1229487
to
fec1854
Compare
I'm sorry, I originally wrote this PR based off of |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I was running into a SwiftUI issue where the
.fontWeight
modifier stopped working when I moved fonts out of my iOS project into and into my shared library via moko-resources.For example:
It took a little bit to track down the problem. After some research, I found
CTFontManagerRegisterGraphicsFont
and laterCTFontManagerRegisterFontsForURL
This PR does a few things:
FontResource
to maximize code sharing, and creates platform-specific FontResourceExt forUIFont
/NSFont
usage.NSErrorException
throwable that wraps anNSError
to make it easier for Swift to inspect the nestedNSError
thrown.registerFont
to the AppleFontResource
, meant to be called during App startup. Once a font is registered, then.fontWeight
works as expected again.fontRef
to a lazy delegate instead of always creating it in the class initializer. With the newregisterFont
, there are scenarios in which it is not necessary to create this reference.fontRef
To use
registerFont()
, enumerate the list of fonts and call it on each one during application startup. Mine looks like this: