Skip to content

Commit 6f2d0d9

Browse files
committed
fix: ios font handling
1 parent fb942ae commit 6f2d0d9

14 files changed

Lines changed: 212 additions & 51 deletions

packages/font-manager/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@nativescript/font-manager",
3-
"version": "1.0.5",
3+
"version": "1.0.6",
44
"description": "A NativeScript plugin for managing fonts",
55
"main": "index",
66
"types": "index.d.ts",

packages/font-manager/src-native/ios/FontManager/Sources/FontManager/NSCFontDescriptors.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
#import <Foundation/Foundation.h>
22
#import "NSCFontTypes.h"
3+
#import "NSCFontStyle.h"
34

45
NS_ASSUME_NONNULL_BEGIN
56

67
@interface NSCFontDescriptors : NSObject
78

89
@property (nonatomic) NSCFontWeight weight;
910
@property (nonatomic, copy) NSString *family;
10-
@property (nonatomic) NSCFontStyle style;
11-
@property (nonatomic, copy, nullable) NSString *obliqueAngle;
11+
@property (nonatomic, strong) NSCFontStyle *style;
1212
@property (nonatomic, copy) NSString *variant;
1313
@property (nonatomic, copy) NSString *ascentOverride;
1414
@property (nonatomic, copy) NSString *descentOverride;

packages/font-manager/src-native/ios/FontManager/Sources/FontManager/NSCFontDescriptors.m

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#import "NSCFontDescriptors.h"
2+
#import "NSCFontStyle.h"
23
#import "NSCFontRegex.h"
34

45
@implementation NSCFontDescriptors
@@ -9,8 +10,7 @@ - (instancetype)initWithFamily:(NSString *)family {
910
if (self) {
1011
_weight = NSCFontWeightNormal;
1112
_family = [family copy];
12-
_style = NSCFontStyleNormal;
13-
_obliqueAngle = nil;
13+
_style = [NSCFontStyle normal];
1414
_variant = @"normal";
1515
_ascentOverride = @"normal";
1616
_descentOverride = @"normal";
@@ -164,20 +164,7 @@ - (void)setFontWeightFromString:(NSString *)value {
164164
}
165165

166166
- (void)setFontStyleFromString:(NSString *)value {
167-
168-
NSString *trimmed = [[value lowercaseString]
169-
stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet];
170-
171-
if ([trimmed hasPrefix:@"oblique"]) {
172-
_style = NSCFontStyleOblique;
173-
NSString *rest = [[trimmed substringFromIndex:@"oblique".length]
174-
stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet];
175-
_obliqueAngle = rest.length > 0 ? rest : @"0deg";
176-
return;
177-
}
178-
179-
_style = NSCFontStyleFromString(trimmed);
180-
_obliqueAngle = nil;
167+
_style = [NSCFontStyle fromString:value];
181168
}
182169

183170
- (void)setFontDisplayFromString:(NSString *)value {

packages/font-manager/src-native/ios/FontManager/Sources/FontManager/NSCFontFace.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#import <Foundation/Foundation.h>
22
#import <CoreGraphics/CoreGraphics.h>
33
#import "NSCFontTypes.h"
4+
#import "NSCFontStyle.h"
45
#import "NSCFontDescriptors.h"
56

67
NS_ASSUME_NONNULL_BEGIN
@@ -17,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN
1718
// Descriptor pass-throughs (mirrors Web FontFace API)
1819
@property (nonatomic) NSCFontDisplay display;
1920
@property (nonatomic) NSCFontWeight weight;
20-
@property (nonatomic) NSCFontStyle style;
21+
@property (nonatomic, strong) NSCFontStyle *style;
2122
@property (nonatomic, copy) NSString *variant;
2223
@property (nonatomic, copy) NSString *stretch;
2324
@property (nonatomic, copy) NSString *unicodeRange;
@@ -70,6 +71,22 @@ NS_ASSUME_NONNULL_BEGIN
7071
*/
7172
- (nullable NSData *)rawData;
7273

74+
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_MACCATALYST
75+
/**
76+
* Returns a UIFont at the given point size, or nil if the face has not been
77+
* loaded yet. The font's weight and italic/oblique traits are applied via
78+
* UIFontDescriptor so they survive dynamic-type scaling by the caller.
79+
*/
80+
- (nullable UIFont *)uiFontWithSize:(CGFloat)size;
81+
82+
/**
83+
* The UIFont for this face at the label font size, set when the face finishes
84+
* loading. Nil until loaded. Rescale with -[UIFont fontWithSize:] as needed.
85+
* Use `uiFontWithSize:` to get a scaled copy in a single call.
86+
*/
87+
@property (nonatomic, readonly, nullable) UIFont *uiFont;
88+
#endif
89+
7390
- (void)updateDescriptor:(NSString *)value;
7491
- (void)updateDescriptorWithValue:(NSString *)value;
7592

packages/font-manager/src-native/ios/FontManager/Sources/FontManager/NSCFontFace.m

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,17 @@
22
#import "NSCFontDescriptors.h"
33
#import "NSCFontFaceSet.h"
44
#import "NSCFontResolver.h"
5+
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_MACCATALYST
6+
#import <UIKit/UIKit.h>
7+
#endif
58

69
@interface NSCFontFace ()
710
@property (nonatomic, copy, nullable) NSString *localOrRemoteSource;
811
@property (nonatomic, copy, nullable) NSString *fontPath;
912
@property (nonatomic, assign) BOOL reloadPending;
13+
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_MACCATALYST
14+
@property (nonatomic, strong, nullable, readwrite) UIFont *uiFont;
15+
#endif
1016
@end
1117

1218
@implementation NSCFontFace
@@ -84,8 +90,8 @@ - (void)setWeight:(NSCFontWeight)weight {
8490
[self _scheduleReloadIfNeeded];
8591
}
8692

87-
- (NSCFontStyle)style { return self.fontDescriptors.style; }
88-
- (void)setStyle:(NSCFontStyle)style {
93+
- (NSCFontStyle *)style { return self.fontDescriptors.style; }
94+
- (void)setStyle:(NSCFontStyle *)style {
8995
self.fontDescriptors.style = style;
9096
[self _scheduleReloadIfNeeded];
9197
}
@@ -248,6 +254,48 @@ - (nullable NSData *)rawData {
248254
return nil;
249255
}
250256

257+
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_MACCATALYST
258+
259+
// Apply italic/oblique trait to a base UIFont via descriptor.
260+
- (UIFont *)_applyStyleTraitsToFont:(UIFont *)base size:(CGFloat)size {
261+
NSCFontStyleType styleType = self.fontDescriptors.style.type;
262+
if (styleType == NSCFontStyleTypeItalic || styleType == NSCFontStyleTypeOblique) {
263+
UIFontDescriptor *desc = [base.fontDescriptor
264+
fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitItalic];
265+
if (desc) {
266+
UIFont *italic = [UIFont fontWithDescriptor:desc size:size];
267+
if (italic) return italic;
268+
}
269+
}
270+
return base;
271+
}
272+
273+
// For system/generic families — re-create UIFont from the resolved family name.
274+
// Falls back to a weight-matched system font so we never return nil.
275+
- (UIFont *)_uiFontFromFamily:(NSString *)family size:(CGFloat)size {
276+
UIFont *base = [UIFont fontWithName:family size:size];
277+
if (!base) {
278+
base = [UIFont systemFontOfSize:size weight:NSCUIFontWeight(self.fontDescriptors.weight)];
279+
}
280+
return [self _applyStyleTraitsToFont:base size:size];
281+
}
282+
283+
// For custom registered fonts — bridge through the PostScript name.
284+
- (nullable UIFont *)_uiFontFromCGFont:(CGFontRef)cgFont size:(CGFloat)size {
285+
CFStringRef psRef = CGFontCopyPostScriptName(cgFont);
286+
if (!psRef) return nil;
287+
NSString *psName = (__bridge_transfer NSString *)psRef;
288+
UIFont *base = [UIFont fontWithName:psName size:size];
289+
if (!base) return nil;
290+
return [self _applyStyleTraitsToFont:base size:size];
291+
}
292+
293+
- (nullable UIFont *)uiFontWithSize:(CGFloat)size {
294+
return [self.uiFont fontWithSize:size];
295+
}
296+
297+
#endif
298+
251299
- (void)_loadInternalWithCompletion:(void (^)(NSString * _Nullable))callback {
252300
NSString *family = self.fontDescriptors.family;
253301
NSString *src = self.localOrRemoteSource;
@@ -257,6 +305,9 @@ - (void)_loadInternalWithCompletion:(void (^)(NSString * _Nullable))callback {
257305
CGFontRef font = [[NSCFontResolver shared] registerFontFromData:self.fontData error:&error];
258306
if (font) {
259307
self.font = font;
308+
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_MACCATALYST
309+
self.uiFont = [self _uiFontFromCGFont:font size:UIFont.labelFontSize];
310+
#endif
260311
self.status = NSCFontFaceStatusLoaded;
261312
callback(nil);
262313
} else {
@@ -285,6 +336,16 @@ - (void)_loadInternalWithCompletion:(void (^)(NSString * _Nullable))callback {
285336
self->_fontPath = src;
286337
}
287338

339+
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_MACCATALYST
340+
// Custom source font: bridge via PostScript name.
341+
// System/generic font (no src): re-create from resolved family name.
342+
if (src.length > 0) {
343+
self.uiFont = [self _uiFontFromCGFont:font size:UIFont.labelFontSize];
344+
} else {
345+
NSString *resolvedFamily = [[NSCFontResolver shared] resolveGenericFamily:family];
346+
self.uiFont = [self _uiFontFromFamily:resolvedFamily size:UIFont.labelFontSize];
347+
}
348+
#endif
288349
self.status = NSCFontFaceStatusLoaded;
289350
callback(nil);
290351
}];

packages/font-manager/src-native/ios/FontManager/Sources/FontManager/NSCFontFaceSet.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ - (BOOL)_isGeneric:(NSString *)family {
237237
for (NSCFontFace *face in candidates) {
238238
NSInteger score =
239239
labs(face.fontDescriptors.weight - parsed.weight) +
240-
(face.fontDescriptors.style == parsed.style ? 0 : 1000);
240+
(face.fontDescriptors.style.type == parsed.style.type ? 0 : 1000);
241241
if (score < bestScore) { bestScore = score; best = face; }
242242
}
243243
if (best) return @[best];

packages/font-manager/src-native/ios/FontManager/Sources/FontManager/NSCFontManagerUmbrella.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#import "NSCFontParser.h"
22
#import "NSCFontTypes.h"
3+
#import "NSCFontStyle.h"
34
#import "NSCFontDescriptors.h"
45
#import "NSCFontFace.h"
56
#import "NSCFontResolver.h"

packages/font-manager/src-native/ios/FontManager/Sources/FontManager/NSCFontParser.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#import <Foundation/Foundation.h>
2-
#import "NSCFontTypes.h"
2+
#import "NSCFontStyle.h"
33

44
NS_ASSUME_NONNULL_BEGIN
55

66
@interface NSCFontParseResult : NSObject
77

8-
@property (nonatomic, assign) NSCFontStyle style;
8+
@property (nonatomic, strong) NSCFontStyle *style;
99
@property (nonatomic, assign) NSInteger weight;
1010
@property (nonatomic, assign) NSInteger sizePx;
1111
@property (nonatomic, strong, nullable) NSNumber *lineHeight;

packages/font-manager/src-native/ios/FontManager/Sources/FontManager/NSCFontParser.m

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#import "NSCFontParser.h"
2+
#import "NSCFontStyle.h"
23

34
@implementation NSCFontParseResult
45
@end
@@ -21,7 +22,7 @@ + (nullable NSCFontParseResult *)parse:(NSString *)input {
2122

2223
NSArray<NSString *> *tokens = [self tokenize:input];
2324

24-
NSCFontStyle style = NSCFontStyleNormal;
25+
NSCFontStyle *style = [NSCFontStyle normal];
2526
NSInteger weight = 400;
2627
NSInteger size = -1;
2728
NSNumber *lineHeight = nil;
@@ -40,11 +41,15 @@ + (nullable NSCFontParseResult *)parse:(NSString *)input {
4041

4142
if ([token isEqualToString:@"italic"]) {
4243

43-
style = NSCFontStyleItalic;
44+
style = [NSCFontStyle italic];
4445

4546
} else if ([token hasPrefix:@"oblique"]) {
4647

47-
style = NSCFontStyleOblique;
48+
NSString *rest = [[token substringFromIndex:@"oblique".length]
49+
stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet];
50+
NSString *digits = [rest hasSuffix:@"deg"] ? [rest substringToIndex:rest.length - 3] : rest;
51+
NSInteger angle = digits.length > 0 ? digits.integerValue : 0;
52+
style = [NSCFontStyle obliqueWithAngle:angle];
4853

4954
} else if ([token isEqualToString:@"bold"]) {
5055

packages/font-manager/src-native/ios/FontManager/Sources/FontManager/NSCFontResolver.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ typedef void (^NSCFontResolverCompletion)(
2727

2828
- (nullable NSData *)loadFontDataFromURL:(NSString *)src error:(NSError **)error;
2929
- (nullable CGFontRef)registerFontFromData:(NSData *)data error:(NSError **)error;
30+
- (NSString *)resolveGenericFamily:(NSString *)family;
3031
- (void)importFromRemoteWithURL:(NSString *)url
3132
load:(BOOL)load
3233
completion:(void (^)(NSArray<NSCFontFace *> * _Nullable fonts,

0 commit comments

Comments
 (0)