Skip to content

Commit

Permalink
fead(ios, android): support load font from JSbundle
Browse files Browse the repository at this point in the history
  • Loading branch information
Cyunong committed Oct 24, 2024
1 parent b8c1816 commit 3b67eac
Show file tree
Hide file tree
Showing 9 changed files with 259 additions and 99 deletions.
6 changes: 3 additions & 3 deletions framework/ios/module/fontLoader/HippyFontLoaderModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ NS_ASSUME_NONNULL_BEGIN
HIPPY_EXTERN NSString *const HippyLoadFontNotification;

typedef NS_ENUM(NSInteger, HippyFontUrlState) {
HippyFontUrlLoading = 0,
HippyFontUrlLoaded = 1,
HippyFontUrlFailed = 2,
HippyFontUrlLoading = 1,
HippyFontUrlLoaded = 2,
HippyFontUrlFailed = 3,
};

@interface HippyFontLoaderModule : NSObject<HippyBridgeModule>
Expand Down
109 changes: 61 additions & 48 deletions framework/ios/module/fontLoader/HippyFontLoaderModule.mm
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#import "HippyBridge+VFSLoader.h"
#import "HippyLog.h"
#import "VFSUriLoader.h"
#import "HippyVFSDefines.h"
#import "HippyUIManager.h"


Expand All @@ -38,17 +39,17 @@
static NSUInteger const FontLoaderErrorRegisterError = 4;
static NSUInteger const FontLoaderErrorWriteFileError = 4;
NSString *const HippyFontDirName = @"HippyFonts";
NSString *const HippyFontUrlCacheName = @"urlToFile.plist";
NSString *const HippyFontUrlCacheName = @"urlToFilePath.plist";
NSString *const HippyFontFamilyCacheName = @"fontFaimilyToFiles.plist";

static dispatch_queue_t serialQueue;
static NSMutableDictionary *urlToFile;
static NSMutableDictionary *urlToFilePath;
static NSMutableDictionary *fontFamilyToFiles;
static NSMutableDictionary *urlLoadState;
static NSMutableArray *fontRegistered = [NSMutableArray array];
static NSString *fontDirPath;
static NSString *fontUrlCachePath;
static NSString *fontFamilyCachePath;
static NSString *fontUrlSavePath;
static NSString *fontFamilySavePath;


@implementation HippyFontLoaderModule
Expand All @@ -67,8 +68,8 @@ - (instancetype)init {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachesDirectory = [paths objectAtIndex:0];
fontDirPath = [cachesDirectory stringByAppendingPathComponent:HippyFontDirName];
fontUrlCachePath = [fontDirPath stringByAppendingPathComponent:HippyFontUrlCacheName];
fontFamilyCachePath = [fontDirPath stringByAppendingPathComponent:HippyFontFamilyCacheName];
fontUrlSavePath = [fontDirPath stringByAppendingPathComponent:HippyFontUrlCacheName];
fontFamilySavePath = [fontDirPath stringByAppendingPathComponent:HippyFontFamilyCacheName];
serialQueue = dispatch_queue_create("com.tencent.hippy.FontLoaderQueue", DISPATCH_QUEUE_SERIAL);
});
}
Expand All @@ -89,15 +90,15 @@ + (BOOL) isUrlLoading:(NSString *)url {

+ (void) initDictIfNeeded {
if (fontFamilyToFiles == nil) {
fontFamilyToFiles = [NSMutableDictionary dictionaryWithContentsOfFile:fontFamilyCachePath];
fontFamilyToFiles = [NSMutableDictionary dictionaryWithContentsOfFile:fontFamilySavePath];
if (fontFamilyToFiles == nil) {
fontFamilyToFiles = [NSMutableDictionary dictionary];
}
}
if (urlToFile == nil) {
urlToFile = [NSMutableDictionary dictionaryWithContentsOfFile:fontUrlCachePath];
if (urlToFile == nil) {
urlToFile = [NSMutableDictionary dictionary];
if (urlToFilePath == nil) {
urlToFilePath = [NSMutableDictionary dictionaryWithContentsOfFile:fontUrlSavePath];
if (urlToFilePath == nil) {
urlToFilePath = [NSMutableDictionary dictionary];
}
}
}
Expand All @@ -110,16 +111,15 @@ - (void)loadFont:(NSNotification *)notification {

+ (NSString *)getFontPath:(NSString *)url {
[self initDictIfNeeded];
NSString *fontFile = urlToFile[url];
if (!fontFile) {
NSString *fontFilePath = urlToFilePath[url];
if (!fontFilePath) {
return nil;
}
NSString *fontPath = [fontDirPath stringByAppendingPathComponent:fontFile];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:fontPath]) {
if (![fileManager fileExistsAtPath:fontFilePath]) {
return nil;
}
return fontPath;
return fontFilePath;
}

+ (void)registerFontIfNeeded:(NSString *)fontFamily {
Expand All @@ -130,9 +130,8 @@ + (void)registerFontIfNeeded:(NSString *)fontFamily {
NSMutableArray *fileNotExist = [NSMutableArray array];
for (NSString *fontFile in fontFiles) {
if (![fontRegistered containsObject:fontFile]) {
NSString *fontFilePath = [fontDirPath stringByAppendingPathComponent:fontFile];
NSError *error = nil;
if ([self registerFontFromURL:fontFilePath error:&error]) {
if ([self registerFontFromURL:fontFile error:&error]) {
[fontRegistered addObject:fontFile];
isFontRegistered = YES;
HippyLogInfo(@"register font \"%@\" success!", fontFile);
Expand Down Expand Up @@ -173,19 +172,19 @@ + (BOOL)registerFontFromURL:(NSString *)urlString error:(NSError **)error {
return YES;
}

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


Expand All @@ -208,20 +207,6 @@ - (void)cacheFontfamily:(NSString *)fontFamily url:(NSString *)url fileName:(NSS
[HippyFontLoaderModule setUrl:urlString state:HippyFontUrlLoading];
}

NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:fontDirPath]) {
NSError *error;
[fileManager createDirectoryAtPath:fontDirPath withIntermediateDirectories:YES attributes:nil error:&error];
if (error) {
NSString *errorKey = [NSString stringWithFormat:@"%lu", FontLoaderErrorDirectoryError];
if (reject) {
reject(errorKey, @"directory create error", error);
}
[HippyFontLoaderModule setUrl:urlString state:HippyFontUrlFailed];
return;
}
}

__weak __typeof(self) weakSelf = self;
[self.bridge loadContentsAsynchronouslyFromUrl:urlString
method:@"Get"
Expand All @@ -239,24 +224,52 @@ - (void)cacheFontfamily:(NSString *)fontFamily url:(NSString *)url fileName:(NSS
[HippyFontLoaderModule setUrl:urlString state:HippyFontUrlFailed];
return;
}
NSString *fileName = [fontFamily stringByAppendingFormat:@".%@", [response.suggestedFilename pathExtension]];
NSString *fontFilePath = [fontDirPath stringByAppendingPathComponent:fileName];
if ([data writeToFile:fontFilePath atomically:YES]) {
// is local file url
if ([userInfo[HippyVFSResponseURLTypeKey] integerValue] == HippyVFSURLTypeFile) {
NSString *fontFilePath = userInfo[HippyVFSResponseAbsoluteURLStringKey] ?: urlString;
dispatch_async([HippyFontLoaderModule getFontSerialQueue], ^{
[strongSelf cacheFontfamily:fontFamily url:urlString fileName:fileName];
[[NSNotificationCenter defaultCenter] postNotificationName:HippyFontChangeTriggerNotification object:nil];
[strongSelf saveFontfamily:fontFamily url:urlString filePath:fontFilePath];
[HippyFontLoaderModule registerFontIfNeeded:fontFamily];
});
if (resolve) {
resolve([NSString stringWithFormat:@"download font file \"%@\" success!", fileName]);
resolve([NSString stringWithFormat:@"load local font file \"%@\" success!", fontFilePath]);
}
[HippyFontLoaderModule setUrl:urlString state:HippyFontUrlLoaded];
}
// is http url
else {
if (reject) {
NSString *errorKey = [NSString stringWithFormat:@"%lu", FontLoaderErrorWriteFileError];
reject(errorKey, @"font request error", error);
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:fontDirPath]) {
NSError *error;
[fileManager createDirectoryAtPath:fontDirPath withIntermediateDirectories:YES attributes:nil error:&error];
if (error) {
NSString *errorKey = [NSString stringWithFormat:@"%lu", FontLoaderErrorDirectoryError];
if (reject) {
reject(errorKey, @"directory create error", error);
}
[HippyFontLoaderModule setUrl:urlString state:HippyFontUrlFailed];
return;
}
}
NSString *fileName = [fontFamily stringByAppendingFormat:@".%@", [response.suggestedFilename pathExtension]];
NSString *fontFilePath = [fontDirPath stringByAppendingPathComponent:fileName];
if ([data writeToFile:fontFilePath atomically:YES]) {
dispatch_async([HippyFontLoaderModule getFontSerialQueue], ^{
[strongSelf saveFontfamily:fontFamily url:urlString filePath:fontFilePath];
[HippyFontLoaderModule registerFontIfNeeded:fontFamily];
});
if (resolve) {
resolve([NSString stringWithFormat:@"download font file \"%@\" success!", fileName]);
}
[HippyFontLoaderModule setUrl:urlString state:HippyFontUrlLoaded];
}
else {
if (reject) {
NSString *errorKey = [NSString stringWithFormat:@"%lu", FontLoaderErrorWriteFileError];
reject(errorKey, @"font request error", error);
}
[HippyFontLoaderModule setUrl:urlString state:HippyFontUrlFailed];
}
[HippyFontLoaderModule setUrl:urlString state:HippyFontUrlFailed];
}
}];
}
Expand Down
11 changes: 7 additions & 4 deletions modules/vfs/ios/HippyFileHandler.mm
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
#include "HippyFileHandler.h"
#include "footstone/logging.h"

NSString *const HippyVFSResponseAbsoluteURLStringKey = @"HippyVFSResponseAbsoluteURLStringKey";
NSString *const HippyVFSResponseURLTypeKey = @"HippyVFSResponseURLTypeKey";

HippyFileHandler::HippyFileHandler(HippyBridge *bridge) {
bridge_ = bridge;
}
Expand Down Expand Up @@ -81,12 +84,12 @@
}
HippyBridge *bridge = bridge_;
if (!bridge || !request) {
completion(nil, nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorUnsupportedURL userInfo:nil]);
completion(nil, @{HippyVFSResponseURLTypeKey: @(HippyVFSURLTypeFile)}, nil, [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorUnsupportedURL userInfo:nil]);
return;
}
NSURL *url = [request URL];
if (!url) {
completion(nil, nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorUnsupportedURL userInfo:nil]);
completion(nil, @{HippyVFSResponseURLTypeKey: @(HippyVFSURLTypeFile)}, nil, [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorUnsupportedURL userInfo:nil]);
return;
}

Expand All @@ -99,7 +102,7 @@
MIMEType:nil
expectedContentLength:fileData.length
textEncodingName:nil];
completion(fileData, nil, rsp, error);
completion(fileData, @{HippyVFSResponseURLTypeKey: @(HippyVFSURLTypeFile), HippyVFSResponseAbsoluteURLStringKey: [absoluteURL path]}, rsp, error);
};
if (queue) {
[queue addOperationWithBlock:opBlock];
Expand All @@ -108,6 +111,6 @@
}
} else {
FOOTSTONE_DLOG(ERROR) << "HippyFileHandler cannot load url " << [[absoluteURL absoluteString] UTF8String];
completion(nil, nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorUnsupportedURL userInfo:nil]);
completion(nil, @{HippyVFSResponseURLTypeKey: @(HippyVFSURLTypeFile)}, nil, [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorUnsupportedURL userInfo:nil]);
}
}
12 changes: 12 additions & 0 deletions modules/vfs/ios/HippyVFSDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ enum HippyVFSRscType {
HippyVFSRscTypeImage,
};

enum HippyVFSURLType {
HippyVFSURLTypeHTTP = 1,
HippyVFSURLTypeFile,
};


// Resource Type Key for VFS Request in `extraInfo` parameter,
// Value is defined in HippyVFSRscType
Expand All @@ -53,6 +58,13 @@ FOUNDATION_EXPORT NSString *_Nonnull const kHippyVFSRequestExtraInfoForCustomIma
// The image returned in `userInfo` parameter of VFSHandlerCompletionBlock
FOUNDATION_EXPORT NSString *_Nonnull const HippyVFSResponseDecodedImageKey;

// The absolute file url returned in `userInfo` parameter of VFSHandlerCompletionBlock
FOUNDATION_EXPORT NSString *_Nonnull const HippyVFSResponseAbsoluteURLStringKey;

// The type of url returned in `userInfo` parameter of VFSHandlerCompletionBlock
// Value is defined in HippyVFSURLType
FOUNDATION_EXPORT NSString *_Nonnull const HippyVFSResponseURLTypeKey;


typedef void(^VFSHandlerProgressBlock)(NSUInteger current, NSUInteger total);
typedef void(^VFSHandlerCompletionBlock)(NSData *_Nullable data,
Expand Down
8 changes: 4 additions & 4 deletions modules/vfs/ios/VFSUriHandler.mm
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ static bool CheckRequestFromCPP(const std::unordered_map<std::string, std::strin
HippyImageLoaderControlOptions options) {
NSDictionary *dict = nil;
if (image && (options & HippyImageLoaderControl_SkipDecodeOrDownsample)) {
dict = @{ HippyVFSResponseDecodedImageKey: image };
dict = @{ HippyVFSResponseDecodedImageKey: image, HippyVFSResponseURLTypeKey: @(HippyVFSURLTypeHTTP)};
}
NSURLResponse *rsp = [[NSURLResponse alloc] initWithURL:url
MIMEType:nil
Expand All @@ -227,7 +227,7 @@ static bool CheckRequestFromCPP(const std::unordered_map<std::string, std::strin
@"NSURLErrorFailingInfo": @"scheme not registered"};
NSInteger code = static_cast<NSInteger>(hippy::JobResponse::RetCode::SchemeNotRegister);
NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:code userInfo:userInfo];
completion(nil, nil, nil, error);
completion(nil, @{HippyVFSResponseURLTypeKey: @(HippyVFSURLTypeHTTP)}, nil, error);
return;
}
NSURLSessionDataProgress *dataProgress = [[NSURLSessionDataProgress alloc] initWithProgress:progress result:completion];
Expand All @@ -247,7 +247,7 @@ static bool CheckRequestFromCPP(const std::unordered_map<std::string, std::strin
@"NSURLErrorFailingInfo": @"loader not found"};
NSInteger code = static_cast<NSInteger>(hippy::JobResponse::RetCode::ResourceNotFound);
NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:code userInfo:userInfo];
completion(nil, nil, nil, error);
completion(nil, @{HippyVFSResponseURLTypeKey: @(HippyVFSURLTypeHTTP)}, nil, error);
return;
}
auto progressCallback = [progress](int64_t current, int64_t total){
Expand All @@ -274,7 +274,7 @@ static bool CheckRequestFromCPP(const std::unordered_map<std::string, std::strin
NSInteger code = static_cast<NSInteger>(cb->GetRetCode());
error = [NSError errorWithDomain:NSURLErrorDomain code:code userInfo:userInfo];
}
completion(data, nil, response, error);
completion(data, @{HippyVFSResponseURLTypeKey: @(HippyVFSURLTypeHTTP)}, response, error);
}
};
loader->hippy::UriLoader::RequestUntrustedContent(requestJob, responseCallback);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -803,11 +803,17 @@ private void updateTypeface() {
mTextPaint.reset();
}
NativeRender nativeRenderer = NativeRendererManager.getNativeRenderer(getContext());
if (mFontUrl != null) {
if (mFontUrl != null && !mFontUrl.isEmpty()) {
FontLoader loader = nativeRenderer == null ? null : nativeRenderer.getFontLoader();
if (loader != null) {
int rootId = nativeRenderer.getRootView(this).getId();
loader.loadIfNeeded(mFontFamily, mFontUrl, rootId);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
loader.loadIfNeeded(mFontFamily, mFontUrl, rootId);
}
});
thread.start();
}
}
FontAdapter fontAdapter = nativeRenderer == null ? null : nativeRenderer.getFontAdapter();
Expand Down
Loading

0 comments on commit 3b67eac

Please sign in to comment.