1 | //
|
2 | // RNVectorIconsManager.m
|
3 | // RNVectorIconsManager
|
4 | //
|
5 | // Created by Joel Arvidsson on 2015-05-29.
|
6 | // Copyright (c) 2015 Joel Arvidsson. All rights reserved.
|
7 | //
|
8 |
|
9 | #import "RNVectorIconsManager.h"
|
10 | #import <CoreText/CoreText.h>
|
11 | #if __has_include(<React/RCTConvert.h>)
|
12 | #import <React/RCTConvert.h>
|
13 | #else // Compatibility for RN version < 0.40
|
14 | #import "RCTConvert.h"
|
15 | #endif
|
16 | #if __has_include(<React/RCTBridge.h>)
|
17 | #import <React/RCTBridge.h>
|
18 | #else // Compatibility for RN version < 0.40
|
19 | #import "RCTBridge.h"
|
20 | #endif
|
21 | #if __has_include(<React/RCTUtils.h>)
|
22 | #import <React/RCTUtils.h>
|
23 | #else // Compatibility for RN version < 0.40
|
24 | #import "RCTUtils.h"
|
25 | #endif
|
26 | #if __has_include(<React/RCTFont.h>)
|
27 | #import <React/RCTFont.h>
|
28 | #else // Compatibility for RN version < 0.40
|
29 | #import "RCTFont.h"
|
30 | #endif
|
31 |
|
32 | NSString *const RNVIErrorDomain = @"org.oblador.react-native-vector-icons";
|
33 |
|
34 | @implementation RNVectorIconsManager
|
35 |
|
36 | @synthesize bridge = _bridge;
|
37 | RCT_EXPORT_MODULE();
|
38 |
|
39 | - (NSString *)hexStringFromColor:(UIColor *)color
|
40 | {
|
41 | const CGFloat *components = CGColorGetComponents(color.CGColor);
|
42 |
|
43 | CGFloat r = components[0];
|
44 | CGFloat g = components[1];
|
45 | CGFloat b = components[2];
|
46 |
|
47 | return [NSString stringWithFormat:@"#%02lX%02lX%02lX",
|
48 | lroundf(r * 255),
|
49 | lroundf(g * 255),
|
50 | lroundf(b * 255)];
|
51 | }
|
52 |
|
53 | - (NSString *)generateFilePath:(NSString *)glyph withFontName:(NSString *)fontName
|
54 | withFontSize:(CGFloat)fontSize
|
55 | withColor:(UIColor *)color
|
56 | withExtraIdentifier:(NSString *)identifier
|
57 | {
|
58 | CGFloat screenScale = RCTScreenScale();
|
59 | NSString *hexColor = [self hexStringFromColor:color];
|
60 | NSString *fileName = [NSString stringWithFormat:@"%@RNVectorIcons_%@_%@_%@_%.f%@@%.fx.png",
|
61 | NSTemporaryDirectory(),
|
62 | identifier, fontName, glyph,
|
63 | fontSize, hexColor, screenScale];
|
64 |
|
65 | return fileName;
|
66 | }
|
67 |
|
68 | - (BOOL)createAndSaveGlyphImage:(NSString *)glyph withFont:(UIFont *)font
|
69 | withFilePath:(NSString *)filePath
|
70 | withColor:(UIColor *)color
|
71 | {
|
72 | if(![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
|
73 | // No cached icon exists, we need to create it and persist to disk
|
74 |
|
75 | NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:glyph attributes:@{NSFontAttributeName: font, NSForegroundColorAttributeName: color}];
|
76 |
|
77 | CGSize iconSize = [attributedString size];
|
78 | UIGraphicsBeginImageContextWithOptions(iconSize, NO, 0.0);
|
79 | [attributedString drawAtPoint:CGPointMake(0, 0)];
|
80 |
|
81 | UIImage *iconImage = UIGraphicsGetImageFromCurrentImageContext();
|
82 | UIGraphicsEndImageContext();
|
83 |
|
84 | NSData *imageData = UIImagePNGRepresentation(iconImage);
|
85 | return [imageData writeToFile:filePath atomically:YES];
|
86 | }
|
87 |
|
88 | return YES;
|
89 | }
|
90 |
|
91 | - (NSString *)createGlyphImagePathForFont:(NSString *)fontName
|
92 | withGlyph:(NSString *)glyph
|
93 | withFontSize:(CGFloat)fontSize
|
94 | withColor:(UIColor *)color
|
95 | withError:(NSError **)error
|
96 | {
|
97 | UIFont *font = [UIFont fontWithName:fontName size:fontSize];
|
98 | NSString *filePath = [self generateFilePath:glyph withFontName:fontName
|
99 | withFontSize:fontSize
|
100 | withColor:color
|
101 | withExtraIdentifier:@""];
|
102 |
|
103 | BOOL success = [self createAndSaveGlyphImage:glyph withFont:font
|
104 | withFilePath:filePath
|
105 | withColor:color];
|
106 |
|
107 | if (!success) {
|
108 | *error = [NSError errorWithDomain:RNVIErrorDomain code:RNVIGenericError userInfo:@{NSLocalizedDescriptionKey: @"Failed to write rendered icon image"}];
|
109 | return nil;
|
110 | }
|
111 | return filePath;
|
112 | }
|
113 |
|
114 | RCT_EXPORT_METHOD(
|
115 | getImageForFont:(NSString *)fontName
|
116 | withGlyph:(NSString *)glyph
|
117 | withFontSize:(CGFloat)fontSize
|
118 | withColor:(UIColor *)color
|
119 | resolver:(RCTPromiseResolveBlock)resolve
|
120 | rejecter:(RCTPromiseRejectBlock)reject
|
121 | ) {
|
122 | NSError *error = nil;
|
123 | NSString *filePath = [self createGlyphImagePathForFont:fontName
|
124 | withGlyph:glyph
|
125 | withFontSize:fontSize
|
126 | withColor:color
|
127 | withError:&error];
|
128 | if (error != nil) {
|
129 | reject([NSString stringWithFormat:@"%ld", (long)error.code], error.localizedDescription, error);
|
130 | } else {
|
131 | resolve(filePath);
|
132 | }
|
133 | }
|
134 |
|
135 | RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(
|
136 | getImageForFontSync:(NSString *)fontName
|
137 | withGlyph:(NSString *)glyph
|
138 | withFontSize:(CGFloat)fontSize
|
139 | withColor:(UIColor *)color
|
140 | ) {
|
141 | NSError *error = nil;
|
142 | return [self createGlyphImagePathForFont:fontName
|
143 | withGlyph:glyph
|
144 | withFontSize:fontSize
|
145 | withColor:color
|
146 | withError:&error];
|
147 | }
|
148 |
|
149 | RCT_EXPORT_METHOD(
|
150 | loadFontWithFileName:(NSString *)fontFileName
|
151 | extension:(NSString *)extension
|
152 | resolver:(RCTPromiseResolveBlock)resolve
|
153 | rejecter:(RCTPromiseRejectBlock)reject
|
154 | ) {
|
155 | NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
156 | NSURL *fontURL = [bundle URLForResource:fontFileName withExtension:extension];
|
157 | NSData *fontData = [NSData dataWithContentsOfURL:fontURL];
|
158 |
|
159 | CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)fontData);
|
160 | CGFontRef font = CGFontCreateWithDataProvider(provider);
|
161 |
|
162 | if (font) {
|
163 | CFErrorRef errorRef = NULL;
|
164 | if (CTFontManagerRegisterGraphicsFont(font, &errorRef) == NO) {
|
165 | NSError *error = (__bridge NSError *)errorRef;
|
166 | if (error.code == kCTFontManagerErrorAlreadyRegistered) {
|
167 | resolve(nil);
|
168 | } else {
|
169 | reject(@"font_load_failed", @"Font failed to load", error);
|
170 | }
|
171 | } else {
|
172 | resolve(nil);
|
173 | }
|
174 |
|
175 | CFRelease(font);
|
176 | }
|
177 | if (provider) {
|
178 | CFRelease(provider);
|
179 | }
|
180 | }
|
181 |
|
182 | @end
|