Skip to content

Commit

Permalink
fix(ios): improve code after discussion
Browse files Browse the repository at this point in the history
  • Loading branch information
Cyunong committed Dec 11, 2024
1 parent cd0a84a commit 4b9c093
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 58 deletions.
11 changes: 9 additions & 2 deletions framework/ios/module/fontLoader/HippyFontLoaderModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@

NS_ASSUME_NONNULL_BEGIN

HIPPY_EXTERN NSString *const HippyLoadFontNotification;

typedef NS_ENUM(NSInteger, HippyFontUrlState) {
HippyFontUrlPending = 0,
HippyFontUrlLoading = 1,
Expand Down Expand Up @@ -58,6 +56,15 @@ typedef NS_ENUM(NSInteger, HippyFontUrlState) {
*/
+ (BOOL)registerFontIfNeeded:(NSString *)fontFamily;

/**
* If the font in the url has not been downloaded, download the font.
* Function will be called when downloading fonts through url property of text component.
*
* @param fontFamily - The font family needs to be downloaded
* @param url - The font url needs to download from.
*/
+ (void)loadFontIfNeeded:(NSString *)fontFamily fromUrl:(NSString *)url;

/**
* Whether the font is downloading from the url.
*
Expand Down
110 changes: 68 additions & 42 deletions framework/ios/module/fontLoader/HippyFontLoaderModule.mm
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,27 @@
#import "HippyUIManager.h"


NSString *const HippyLoadFontNotification = @"HippyLoadFontNotification";
static NSString *const HippyLoadFontNotification = @"HippyLoadFontNotification";
static NSString *const HippyLoadFontUrlKey = @"fontUrl";
static NSString *const HippyLoadFontFamilyKey = @"fontFamily";
static NSString *const kFontLoaderModuleErrorDomain = @"kFontLoaderModuleErrorDomain";
static NSUInteger const FontLoaderErrorUrlError = 1;
static NSUInteger const FontLoaderErrorDirectoryError = 2;
static NSUInteger const FontLoaderErrorRequestError = 3;
static NSUInteger const FontLoaderErrorRegisterError = 4;
static NSUInteger const FontLoaderErrorWriteFileError = 4;
NSString *const HippyFontDirName = @"HippyFonts";
NSString *const HippyFontUrlCacheName = @"urlToFilePath.plist";
NSString *const HippyFontFamilyCacheName = @"fontFaimilyToFiles.plist";
static NSString *const HippyFontDirName = @"HippyFonts";
static NSString *const HippyFontUrlCacheName = @"urlToFilePath.plist";
static NSString *const HippyFontFamilyCacheName = @"fontFaimilyToFiles.plist";

static dispatch_queue_t serialQueue;
static NSMutableDictionary *urlToFilePath;
static NSMutableDictionary *fontFamilyToFiles;
static NSMutableDictionary *urlLoadState = [NSMutableDictionary dictionary];
static NSMutableArray *fontRegistered = [NSMutableArray array];
static NSString *fontDirPath;
static NSString *fontUrlSavePath;
static NSString *fontFamilySavePath;
static dispatch_queue_t gSerialQueue;
static NSMutableDictionary *gUrlToFilePath;
static NSMutableDictionary *gFontFamilyToFiles;
static NSMutableDictionary *gUrlLoadState;
static NSMutableArray *gFontRegistered;
static NSString *gFontDirPath;
static NSString *gFontUrlSavePath;
static NSString *gFontFamilySavePath;


@implementation HippyFontLoaderModule
Expand All @@ -67,51 +69,70 @@ - (instancetype)init {

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachesDirectory = [paths objectAtIndex:0];
fontDirPath = [cachesDirectory stringByAppendingPathComponent:HippyFontDirName];
fontUrlSavePath = [fontDirPath stringByAppendingPathComponent:HippyFontUrlCacheName];
fontFamilySavePath = [fontDirPath stringByAppendingPathComponent:HippyFontFamilyCacheName];
serialQueue = dispatch_queue_create("com.tencent.hippy.FontLoaderQueue", DISPATCH_QUEUE_SERIAL);
gFontDirPath = [cachesDirectory stringByAppendingPathComponent:HippyFontDirName];
gFontUrlSavePath = [gFontDirPath stringByAppendingPathComponent:HippyFontUrlCacheName];
gFontFamilySavePath = [gFontDirPath stringByAppendingPathComponent:HippyFontFamilyCacheName];
gSerialQueue = dispatch_queue_create("com.tencent.hippy.FontLoaderQueue", DISPATCH_QUEUE_SERIAL);
});
}
return self;
}

+ (dispatch_queue_t)getFontSerialQueue {
return serialQueue;
return gSerialQueue;
}

+ (void)setUrl:(NSString *)url state:(HippyFontUrlState)state {
[urlLoadState setObject:@(state) forKey:url];
if (!gUrlLoadState) {
gUrlLoadState = [NSMutableDictionary dictionary];
}
[gUrlLoadState setObject:@(state) forKey:url];
}

+ (BOOL)isUrlLoading:(NSString *)url {
return [[urlLoadState objectForKey:url] integerValue] == HippyFontUrlLoading;
if (!gUrlLoadState) {
gUrlLoadState = [NSMutableDictionary dictionary];
}
return [[gUrlLoadState objectForKey:url] integerValue] == HippyFontUrlLoading;
}

// Read file to init dict if needed. This function will be called asynchronously.
+ (void)initDictIfNeeded {
if (fontFamilyToFiles == nil) {
fontFamilyToFiles = [NSMutableDictionary dictionaryWithContentsOfFile:fontFamilySavePath];
if (fontFamilyToFiles == nil) {
fontFamilyToFiles = [NSMutableDictionary dictionary];
if (gFontFamilyToFiles == nil) {
gFontFamilyToFiles = [NSMutableDictionary dictionaryWithContentsOfFile:gFontFamilySavePath];
if (gFontFamilyToFiles == nil) {
gFontFamilyToFiles = [NSMutableDictionary dictionary];
}
}
if (urlToFilePath == nil) {
urlToFilePath = [NSMutableDictionary dictionaryWithContentsOfFile:fontUrlSavePath];
if (urlToFilePath == nil) {
urlToFilePath = [NSMutableDictionary dictionary];
if (gUrlToFilePath == nil) {
gUrlToFilePath = [NSMutableDictionary dictionaryWithContentsOfFile:gFontUrlSavePath];
if (gUrlToFilePath == nil) {
gUrlToFilePath = [NSMutableDictionary dictionary];
}
}
}

+ (void)loadFontIfNeeded:(NSString *)fontFamily fromUrl:(NSString *)url {
if (url && ![HippyFontLoaderModule isUrlLoading:url]) {
dispatch_async([HippyFontLoaderModule getFontSerialQueue], ^{
NSString *fontPath = [HippyFontLoaderModule getFontPath:url];
if (!fontPath && fontFamily) {
NSDictionary *userInfo = @{HippyLoadFontUrlKey: url, HippyLoadFontFamilyKey: fontFamily};
[[NSNotificationCenter defaultCenter] postNotificationName:HippyLoadFontNotification object:nil userInfo:userInfo];
}
});
}
}

- (void)loadFont:(NSNotification *)notification {
NSString *urlString = [notification.userInfo objectForKey:@"fontUrl"];
NSString *fontFamily = [notification.userInfo objectForKey:@"fontFamily"];
NSString *urlString = [notification.userInfo objectForKey:HippyLoadFontUrlKey];
NSString *fontFamily = [notification.userInfo objectForKey:HippyLoadFontFamilyKey];
[self load:fontFamily from:urlString resolver:nil rejecter:nil];
}

+ (NSString *)getFontPath:(NSString *)url {
[self initDictIfNeeded];
NSString *fontFilePath = urlToFilePath[url];
NSString *fontFilePath = gUrlToFilePath[url];
if (!fontFilePath) {
return nil;
}
Expand All @@ -124,15 +145,18 @@ + (NSString *)getFontPath:(NSString *)url {

+ (BOOL)registerFontIfNeeded:(NSString *)fontFamily {
[self initDictIfNeeded];
NSMutableArray *fontFiles = [fontFamilyToFiles objectForKey:fontFamily];
NSMutableArray *fontFiles = [gFontFamilyToFiles objectForKey:fontFamily];
if (!gFontRegistered) {
gFontRegistered = [NSMutableArray array];
}
BOOL isFontRegistered = NO;
if (fontFiles) {
NSMutableArray *fileNotExist = [NSMutableArray array];
for (NSString *fontFile in fontFiles) {
if (![fontRegistered containsObject:fontFile]) {
if (![gFontRegistered containsObject:fontFile]) {
NSError *error = nil;
if ([self registerFontFromURL:fontFile error:&error]) {
[fontRegistered addObject:fontFile];
[gFontRegistered addObject:fontFile];
isFontRegistered = YES;
HippyLogInfo(@"register font \"%@\" success!", fontFile);
} else {
Expand Down Expand Up @@ -174,16 +198,16 @@ + (BOOL)registerFontFromURL:(NSString *)urlString error:(NSError **)error {

- (void)saveFontfamily:(NSString *)fontFamily url:(NSString *)url filePath:(NSString *)filePath {
[HippyFontLoaderModule initDictIfNeeded];
[urlToFilePath setObject:filePath forKey:url];
NSMutableArray *fontFiles = [fontFamilyToFiles objectForKey:fontFamily];
[gUrlToFilePath setObject:filePath forKey:url];
NSMutableArray *fontFiles = [gFontFamilyToFiles objectForKey:fontFamily];
if (!fontFiles) {
fontFiles = [NSMutableArray arrayWithObject:filePath];
[fontFamilyToFiles setObject:fontFiles forKey:fontFamily];
[gFontFamilyToFiles setObject:fontFiles forKey:fontFamily];
} else {
[fontFiles addObject:filePath];
}
[urlToFilePath writeToFile:fontUrlSavePath atomically:YES];
[fontFamilyToFiles writeToFile:fontFamilySavePath atomically:YES];
[gUrlToFilePath writeToFile:gFontUrlSavePath atomically:YES];
[gFontFamilyToFiles writeToFile:gFontFamilySavePath atomically:YES];
}


Expand Down Expand Up @@ -233,12 +257,14 @@ - (void)saveFontfamily:(NSString *)fontFamily url:(NSString *)url filePath:(NSSt
if (resolve) {
resolve([NSString stringWithFormat:@"load local font file \"%@\" success!", fontFilePath]);
}
[HippyFontLoaderModule setUrl:urlString state:HippyFontUrlLoaded];
@synchronized (strongSelf) {
[HippyFontLoaderModule setUrl:urlString state:HippyFontUrlLoaded];
}
} else { // is http url
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:fontDirPath]) {
if (![fileManager fileExistsAtPath:gFontDirPath]) {
NSError *error;
[fileManager createDirectoryAtPath:fontDirPath withIntermediateDirectories:YES attributes:nil error:&error];
[fileManager createDirectoryAtPath:gFontDirPath withIntermediateDirectories:YES attributes:nil error:&error];
if (error) {
NSString *errorKey = [NSString stringWithFormat:@"%lu", FontLoaderErrorDirectoryError];
if (reject) {
Expand All @@ -249,7 +275,7 @@ - (void)saveFontfamily:(NSString *)fontFamily url:(NSString *)url filePath:(NSSt
}
}
NSString *fileName = [fontFamily stringByAppendingFormat:@".%@", [response.suggestedFilename pathExtension]];
NSString *fontFilePath = [fontDirPath stringByAppendingPathComponent:fileName];
NSString *fontFilePath = [gFontDirPath stringByAppendingPathComponent:fileName];
if ([data writeToFile:fontFilePath atomically:YES]) {
dispatch_async([HippyFontLoaderModule getFontSerialQueue], ^{
[strongSelf saveFontfamily:fontFamily url:urlString filePath:fontFilePath];
Expand Down
22 changes: 8 additions & 14 deletions renderer/native/ios/renderer/HippyFont.mm
Original file line number Diff line number Diff line change
Expand Up @@ -206,17 +206,11 @@ + (UIFont *)updateFont:(UIFont *)font
variant:(NSArray<NativeRenderFontVariantDescriptor *> *)variant
scaleMultiplier:(CGFloat)scaleMultiplier {
// Defaults
if (url && ![HippyFontLoaderModule isUrlLoading:url]) {
if (url) {
dispatch_async([HippyFontLoaderModule getFontSerialQueue], ^{
NSString *fontPath = [HippyFontLoaderModule getFontPath:url];
if (!fontPath && family) {
NSDictionary *userInfo = @{@"fontUrl": url, @"fontFamily": family};
[[NSNotificationCenter defaultCenter] postNotificationName:HippyLoadFontNotification object:nil userInfo:userInfo];
}
[HippyFontLoaderModule loadFontIfNeeded:family fromUrl:url];
});
}

// Defaults
static NSString *defaultFontFamily;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Expand Down Expand Up @@ -252,12 +246,6 @@ + (UIFont *)updateFont:(UIFont *)font
fontWeight = weight ? [HippyConvert NativeRenderFontWeight:weight] : fontWeight;

BOOL didFindFont = NO;

if (fontNamesForFamilyName(familyName).count == 0) {
dispatch_async([HippyFontLoaderModule getFontSerialQueue], ^{
[HippyFontLoaderModule registerFontIfNeeded:familyName];
});
}

// Handle system font as special case. This ensures that we preserve
// the specific metrics of the standard system font as closely as possible.
Expand All @@ -280,6 +268,12 @@ + (UIFont *)updateFont:(UIFont *)font
}
}
}

if (!didFindFont && fontNamesForFamilyName(familyName).count == 0) {
dispatch_async([HippyFontLoaderModule getFontSerialQueue], ^{
[HippyFontLoaderModule registerFontIfNeeded:familyName];
});
}

// Gracefully handle being given a font name rather than font family, for
// example: "Helvetica Light Oblique" rather than just "Helvetica".
Expand Down

0 comments on commit 4b9c093

Please sign in to comment.