1// Copyright 2015-present 650 Industries. All rights reserved.
2
3#import <EXFont/EXFontLoader.h>
4#import <EXFont/EXFontLoaderProcessor.h>
5#import <ExpoModulesCore/EXFontManagerInterface.h>
6#import <ExpoModulesCore/EXFontScalersManagerInterface.h>
7#import <EXFont/EXFontScaler.h>
8#import <EXFont/EXFont.h>
9#import <objc/runtime.h>
10#import <EXFont/EXFontManager.h>
11#import <EXFont/EXFontScalersManager.h>
12
13@interface EXFontLoader ()
14
15@property (nonatomic, strong) EXFontScaler *scaler;
16@property (nonatomic, strong) EXFontLoaderProcessor *processor;
17@property (nonatomic, strong) EXFontManager *manager;
18
19@end
20
21@implementation EXFontLoader
22
23EX_EXPORT_MODULE(ExpoFontLoader);
24
25- (instancetype)init
26{
27  if (self = [super init]) {
28    _scaler = [[EXFontScaler alloc] init];
29    _manager = [[EXFontManager alloc] init];
30    _processor = [[EXFontLoaderProcessor alloc] initWithManager:_manager];
31  }
32  return self;
33}
34
35- (instancetype)initWithFontFamilyPrefix:(NSString *)prefix
36{
37  if (self = [super init]) {
38    _scaler = [[EXFontScaler alloc] init];
39    _manager = [[EXFontManager alloc] init];
40    _processor = [[EXFontLoaderProcessor alloc] initWithFontFamilyPrefix:prefix manager:_manager];
41  }
42  return self;
43}
44
45
46- (void)setModuleRegistry:(EXModuleRegistry *)moduleRegistry
47{
48  if (moduleRegistry) {
49    id<EXFontManagerInterface> manager = [moduleRegistry getModuleImplementingProtocol:@protocol(EXFontManagerInterface)];
50    [manager addFontProcessor:_processor];
51
52    id<EXFontScalersManagerInterface> scalersManager = [moduleRegistry getSingletonModuleForName:@"FontScalersManager"];
53    [scalersManager registerFontScaler:_scaler];
54  }
55}
56
57EX_EXPORT_METHOD_AS(loadAsync,
58                    loadAsyncWithFontFamilyName:(NSString *)fontFamilyName
59                    withLocalUri:(NSString *)path
60                    resolver:(EXPromiseResolveBlock)resolve
61                    rejecter:(EXPromiseRejectBlock)reject)
62{
63  if ([_manager fontForName:fontFamilyName]) {
64    reject(@"E_FONT_ALREADY_EXISTS",
65           [NSString stringWithFormat:@"Font with family name '%@' already loaded", fontFamilyName],
66           nil);
67    return;
68  }
69
70  // TODO(nikki): make sure path is in experience's scope
71  NSURL *uriString = [[NSURL alloc] initWithString:path];
72  NSData *data = [[NSFileManager defaultManager] contentsAtPath:[uriString path]];
73  if (!data) {
74    reject(@"E_FONT_FILE_NOT_FOUND",
75           [NSString stringWithFormat:@"File '%@' for font '%@' doesn't exist", path, fontFamilyName],
76           nil);
77    return;
78  }
79
80  CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
81  CGFontRef font = CGFontCreateWithDataProvider(provider);
82  CGDataProviderRelease(provider);
83  if (!font) {
84    reject(@"E_FONT_CREATION_FAILED",
85           [NSString stringWithFormat:@"Could not create font from loaded data for '%@'", fontFamilyName],
86           nil);
87    return;
88  }
89
90  [_manager setFont:[[EXFont alloc] initWithCGFont:font] forName:fontFamilyName];
91  resolve(nil);
92}
93
94@end
95