mirror of
https://github.com/rive-app/rive-ios.git
synced 2026-01-18 17:11:28 +01:00
fix(apple): better release and null checking on fallback fonts (#10562) e0baf4e1fa
* fix(apple): do not use symbolic trait font copy on failure * fix(apple): release ctfont copy * refactor(apple): do not manually ref rcp'd font, remove cache Co-authored-by: David Skuza <david@rive.app>
This commit is contained in:
@@ -1 +1 @@
|
||||
15a6eedc710136a0ca313d4a1708da8b2235382c
|
||||
e0baf4e1faa8b094aea8c7a4aa6155da9b613dac
|
||||
|
||||
@@ -135,8 +135,6 @@
|
||||
F2ECC23A2C66B949008B20E5 /* RiveFontTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2ECC2382C66B920008B20E5 /* RiveFontTests.swift */; };
|
||||
F2FD94042CC9492B00C1FC85 /* RiveFont.m in Sources */ = {isa = PBXBuildFile; fileRef = F2FD94032CC9492B00C1FC85 /* RiveFont.m */; };
|
||||
F2FD94052CC9492B00C1FC85 /* RiveFont.h in Headers */ = {isa = PBXBuildFile; fileRef = F2FD94022CC9492B00C1FC85 /* RiveFont.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
F2FD94082CC94B1A00C1FC85 /* RiveFallbackFontCache.m in Sources */ = {isa = PBXBuildFile; fileRef = F2FD94072CC94B1A00C1FC85 /* RiveFallbackFontCache.m */; };
|
||||
F2FD94092CC94B1A00C1FC85 /* RiveFallbackFontCache.h in Headers */ = {isa = PBXBuildFile; fileRef = F2FD94062CC94B1A00C1FC85 /* RiveFallbackFontCache.h */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -283,8 +281,6 @@
|
||||
F2ECC2382C66B920008B20E5 /* RiveFontTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RiveFontTests.swift; sourceTree = "<group>"; };
|
||||
F2FD94022CC9492B00C1FC85 /* RiveFont.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RiveFont.h; sourceTree = "<group>"; };
|
||||
F2FD94032CC9492B00C1FC85 /* RiveFont.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = RiveFont.m; sourceTree = "<group>"; };
|
||||
F2FD94062CC94B1A00C1FC85 /* RiveFallbackFontCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RiveFallbackFontCache.h; sourceTree = "<group>"; };
|
||||
F2FD94072CC94B1A00C1FC85 /* RiveFallbackFontCache.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = RiveFallbackFontCache.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -508,8 +504,6 @@
|
||||
F2D285482C6D469900728340 /* RiveFallbackFontProvider.swift */,
|
||||
F2FD94022CC9492B00C1FC85 /* RiveFont.h */,
|
||||
F2FD94032CC9492B00C1FC85 /* RiveFont.m */,
|
||||
F2FD94062CC94B1A00C1FC85 /* RiveFallbackFontCache.h */,
|
||||
F2FD94072CC94B1A00C1FC85 /* RiveFallbackFontCache.m */,
|
||||
);
|
||||
path = Fonts;
|
||||
sourceTree = "<group>";
|
||||
@@ -606,7 +600,6 @@
|
||||
F2FD94052CC9492B00C1FC85 /* RiveFont.h in Headers */,
|
||||
04BE5436264D2A7500427B39 /* RivePrivateHeaders.h in Headers */,
|
||||
C9C73EE224FC478900EF9516 /* RiveRuntime.h in Headers */,
|
||||
F2FD94092CC94B1A00C1FC85 /* RiveFallbackFontCache.h in Headers */,
|
||||
83DE4CA72AAAE72100B88B72 /* RenderContext.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -782,7 +775,6 @@
|
||||
F259E5872D35B91700B78FEF /* RiveDataBindingViewModel.mm in Sources */,
|
||||
F21C3D1B2DDFCD93005F82F4 /* RiveRenderImage+Extensions.swift in Sources */,
|
||||
046FB7FF264EAA61000129B1 /* RiveFile.mm in Sources */,
|
||||
F2FD94082CC94B1A00C1FC85 /* RiveFallbackFontCache.m in Sources */,
|
||||
046FB7F2264EAA60000129B1 /* RiveArtboard.mm in Sources */,
|
||||
F2610DD22CA5B4C40090D50B /* RiveLogger+StateMachine.swift in Sources */,
|
||||
046FB7F4264EAA60000129B1 /* RiveLinearAnimationInstance.mm in Sources */,
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
//
|
||||
// RiveFallbackFontCache.h
|
||||
// RiveRuntime
|
||||
//
|
||||
// Created by David Skuza on 10/23/24.
|
||||
// Copyright © 2024 Rive. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <rive/text/font_hb.hpp>
|
||||
#import <RiveRuntime/RiveRuntime-Swift.h>
|
||||
|
||||
@class RiveFontStyle;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// An object that can be used as a dictionary key when caching fallback fonts.
|
||||
/// - Note: This implements NSCopying and overrides `isEqual` and `hash` to add
|
||||
/// support for an object of this type to be used as a key in dictionaries.
|
||||
@interface RiveFallbackFontCacheKey : NSObject <NSCopying>
|
||||
/// The style of the requested fallback font to be cached.
|
||||
@property(nonatomic, readonly, nonnull) RiveFontStyle* style;
|
||||
/// The actual character for which a fallback font is being requested.
|
||||
@property(nonatomic, readonly) rive::Unichar character;
|
||||
/// The fallback index used when originally requesting a fallback.
|
||||
@property(nonatomic, readonly) uint32_t index;
|
||||
- (instancetype)initWithStyle:(RiveFontStyle*)style
|
||||
character:(rive::Unichar)character
|
||||
index:(uint32_t)index;
|
||||
@end
|
||||
|
||||
/// An object that can be used as a dictionary value (typically keyed to
|
||||
/// `RiveFallbackFontCacheKey`), which contains the cached font types.
|
||||
@interface RiveFallbackFontCacheValue : NSObject
|
||||
/// The native font type used as the fallback (passed to the C++
|
||||
/// runtime). On iOS, this will be UIFont. On macOS, this
|
||||
/// will be NSFont.
|
||||
@property(nonatomic, readonly) id font;
|
||||
/// Whether the font used the system shaper (i.e Core Text over Harfbuzz)
|
||||
@property(nonatomic, readonly) BOOL usesSystemShaper;
|
||||
- (instancetype)initWithFont:(id)font usesSystemShaper:(BOOL)usesSystemShaper;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -1,85 +0,0 @@
|
||||
//
|
||||
// RiveFallbackFontCache.m
|
||||
// RiveRuntime
|
||||
//
|
||||
// Created by David Skuza on 10/23/24.
|
||||
// Copyright © 2024 Rive. All rights reserved.
|
||||
//
|
||||
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
#import "RiveFallbackFontCache.h"
|
||||
#import "RiveFont.h"
|
||||
|
||||
@implementation RiveFallbackFontCacheKey
|
||||
@synthesize style = _style;
|
||||
@synthesize character = _character;
|
||||
@synthesize index = _index;
|
||||
|
||||
- (instancetype)initWithStyle:(RiveFontStyle*)style
|
||||
character:(rive::Unichar)character
|
||||
index:(uint32_t)index
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
_style = style;
|
||||
_character = character;
|
||||
_index = index;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if (object == nil)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (![object isKindOfClass:[RiveFallbackFontCacheKey class]])
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (self == object)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
RiveFallbackFontCacheKey* other = (RiveFallbackFontCacheKey*)object;
|
||||
return [self.style isEqual:other.style] &&
|
||||
self.character == other.character && self.index == other.index;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash
|
||||
{
|
||||
// This is a super basic hash function that may be able to be improved.
|
||||
// However, I don't imagine many collisions will happen based on the
|
||||
// simplicity of our current use case. - David
|
||||
return [self.style hash] ^ self.character ^ self.index;
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone*)zone
|
||||
{
|
||||
return [[RiveFallbackFontCacheKey alloc] initWithStyle:[self.style copy]
|
||||
character:self.character
|
||||
index:self.index];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RiveFallbackFontCacheValue
|
||||
@synthesize font = _font;
|
||||
@synthesize usesSystemShaper = _usesSystemShaper;
|
||||
|
||||
- (instancetype)initWithFont:(id)font usesSystemShaper:(BOOL)usesSystemShaper;
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
_font = font;
|
||||
_usesSystemShaper = usesSystemShaper;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
#endif
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#import "RiveFont.h"
|
||||
#import "RiveFallbackFontCache.h"
|
||||
#import <rive/text/font_hb.hpp>
|
||||
#import <RiveRuntime/RiveRuntime-Swift.h>
|
||||
#import <CoreText/CoreText.h>
|
||||
|
||||
@@ -99,10 +99,6 @@ static RiveFontStyleWeight RiveFontStyleWeightFromFloat(float value)
|
||||
}
|
||||
@end
|
||||
|
||||
/// A cache of all used (Rive) fonts, keyed by style and character.
|
||||
static NSMutableDictionary<RiveFallbackFontCacheKey*,
|
||||
RiveFallbackFontCacheValue*>* _fallbackFontCache =
|
||||
nil;
|
||||
/// A user-specified array of fallback fonts.
|
||||
static NSArray<id<RiveFallbackFontProvider>>* _fallbackFonts = nil;
|
||||
/// A user-specified block that returns usable font providers.
|
||||
@@ -144,27 +140,6 @@ static rive::rcp<rive::Font> findFallbackFont(const rive::Unichar missing,
|
||||
float value = hbFont->getWeight();
|
||||
RiveFontStyle* style = [[RiveFontStyle alloc] initWithRawWeight:value];
|
||||
|
||||
// Using the above style, check the cache keyed by the given style and
|
||||
// missing character.
|
||||
RiveFallbackFontCacheKey* cache =
|
||||
[[RiveFallbackFontCacheKey alloc] initWithStyle:style
|
||||
character:missing
|
||||
index:fallbackIndex];
|
||||
|
||||
// If there is a cached fallback font, use that.
|
||||
RiveFallbackFontCacheValue* cachedValue = _fallbackFontCache[cache];
|
||||
if (cachedValue != nil)
|
||||
{
|
||||
auto font = riveFontFromNativeFont(cachedValue.font,
|
||||
cachedValue.usesSystemShaper);
|
||||
rive::rcp<rive::Font> rcFont = rive::rcp<rive::Font>(font);
|
||||
// because the font was released at load time, we need to give
|
||||
// it an extra ref whenever we bump it to a reference counted
|
||||
// pointer.
|
||||
rcFont->ref();
|
||||
return rcFont;
|
||||
}
|
||||
|
||||
// Otherwise, request possible fallback providers based on the missing
|
||||
// character and style. fallbackFontsCallback will always be non-nil,
|
||||
// and use a default array if no explicit callback has been set.
|
||||
@@ -178,18 +153,7 @@ static rive::rcp<rive::Font> findFallbackFont(const rive::Unichar missing,
|
||||
id fallbackFont = provider.fallbackFont;
|
||||
BOOL usesSystemShaper = fallbackIndex >= providers.count;
|
||||
auto font = riveFontFromNativeFont(fallbackFont, usesSystemShaper);
|
||||
rive::rcp<rive::Font> rcFont = rive::rcp<rive::Font>(font);
|
||||
// because the font was released at load time, we need to give
|
||||
// it an extra ref whenever we bump it to a reference counted
|
||||
// pointer.
|
||||
rcFont->ref();
|
||||
|
||||
// Once we've used a font, cache it for later use.
|
||||
_fallbackFontCache[cache] =
|
||||
[[RiveFallbackFontCacheValue alloc] initWithFont:fallbackFont
|
||||
usesSystemShaper:usesSystemShaper];
|
||||
|
||||
return rcFont;
|
||||
return rive::rcp<rive::Font>(font);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -207,7 +171,6 @@ static rive::rcp<rive::Font> findFallbackFont(const rive::Unichar missing,
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
rive::Font::gFallbackProc = findFallbackFont;
|
||||
#endif
|
||||
_fallbackFontCache = [NSMutableDictionary dictionary];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFont:(rive::rcp<rive::Font>)font
|
||||
@@ -250,7 +213,6 @@ static rive::rcp<rive::Font> findFallbackFont(const rive::Unichar missing,
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
// Set the user-specified fallbacks, and reset the cache.
|
||||
_fallbackFonts = [fallbackFonts copy];
|
||||
_fallbackFontCache = [NSMutableDictionary dictionary];
|
||||
|
||||
// "Reset" fallback fonts callback so that array can take priority
|
||||
_fallbackFontsCallback = nil;
|
||||
@@ -262,7 +224,6 @@ static rive::rcp<rive::Font> findFallbackFont(const rive::Unichar missing,
|
||||
#ifdef WITH_RIVE_TEXT
|
||||
// Set the user-specified fallback block, and reset the cache.
|
||||
_fallbackFontsCallback = [fallbackFontCallback copy];
|
||||
_fallbackFontCache = [NSMutableDictionary dictionary];
|
||||
|
||||
// "Reset" fallback fonts array so that callback can take priority
|
||||
_fallbackFonts = nil;
|
||||
|
||||
Submodule submodules/rive-runtime updated: d68ddf26c6...51b62ae8d8
Reference in New Issue
Block a user