Skip to content

Commit 24b3a1d

Browse files
Alberto MarinesAlberto Marines
authored andcommitted
Support flatHeighs iOS
1 parent 7fe568a commit 24b3a1d

File tree

1 file changed

+66
-4
lines changed

1 file changed

+66
-4
lines changed

ios/RNTextSize.m

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,6 @@ - (NSDictionary *)constantsToExport {
6868
// iOS standard sizes
6969
NSDictionary *fontSize = @{
7070
@"default": @(14),
71-
@"button": @([UIFont buttonFontSize]), // 18
72-
@"label": @([UIFont labelFontSize]), // 17
73-
@"smallSystem": @([UIFont smallSystemFontSize]), // 12
74-
@"system": @([UIFont systemFontSize]), // 14
7571
};
7672
return @{@"FontSize": fontSize};
7773
}
@@ -168,6 +164,72 @@ - (NSDictionary *)constantsToExport {
168164
resolve(result);
169165
}
170166

167+
/**
168+
* Gets the width, height, line count and last line width for the provided text
169+
* font specifications.
170+
* Based on `RCTTextShadowViewMeasure` of Libraries/Text/Text/RCTTextShadowView.m
171+
*/
172+
RCT_EXPORT_METHOD(flatHeights:(NSDictionary * _Nullable)options
173+
resolver:(RCTPromiseResolveBlock)resolve
174+
rejecter:(RCTPromiseRejectBlock)reject)
175+
{
176+
NSArray<NSString *> *const _Nullable texts = [RCTConvert NSStringArray:options[@"text"]];
177+
if (isNull(texts)) {
178+
reject(E_MISSING_TEXT, @"Missing required text, must be an array.", nil);
179+
return;
180+
}
181+
182+
UIFont *const _Nullable font = [RNTextSize UIFontFromUserSpecs:options withBridge:_bridge];
183+
if (!font) {
184+
reject(E_INVALID_FONT_SPEC, @"Invalid font specification.", nil);
185+
return;
186+
}
187+
188+
const CGFloat optWidth = CGFloatValueFrom(options[@"width"]);
189+
const CGFloat maxWidth = isnan(optWidth) || isinf(optWidth) ? CGFLOAT_MAX : optWidth;
190+
const CGSize maxSize = CGSizeMake(maxWidth, CGFLOAT_MAX);
191+
192+
// Create attributes for the font and the optional letter spacing.
193+
const CGFloat letterSpacing = CGFloatValueFrom(options[@"letterSpacing"]);
194+
NSDictionary<NSAttributedStringKey,id> *const attributes = isnan(letterSpacing)
195+
? @{NSFontAttributeName: font}
196+
: @{NSFontAttributeName: font, NSKernAttributeName: @(letterSpacing)};
197+
198+
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:maxSize];
199+
textContainer.lineFragmentPadding = 0.0;
200+
textContainer.lineBreakMode = NSLineBreakByClipping; // no maxlines support
201+
202+
NSLayoutManager *layoutManager = [NSLayoutManager new];
203+
[layoutManager addTextContainer:textContainer];
204+
205+
NSMutableArray<NSNumber *> *result = [[NSMutableArray alloc] initWithCapacity:texts.count];
206+
const CGFloat epsilon = 1 / RCTScreenScale(); // Yoga seems do this
207+
208+
for (int ix = 0; ix < texts.count; ix++) {
209+
NSString *text = texts[ix];
210+
if (!text) {
211+
result[ix] = @0;
212+
continue;
213+
}
214+
if (text == (id) kCFNull) {
215+
result[ix] = @0;
216+
continue;
217+
}
218+
219+
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString:text attributes:attributes];
220+
[textStorage addLayoutManager:layoutManager];
221+
222+
[layoutManager ensureLayoutForTextContainer:textContainer];
223+
CGSize size = [layoutManager usedRectForTextContainer:textContainer].size;
224+
[textStorage removeLayoutManager:layoutManager];
225+
226+
const CGFloat height = MIN(RCTCeilPixelValue(size.height + epsilon), maxSize.height);
227+
result[ix] = @(height);
228+
}
229+
230+
resolve(result);
231+
}
232+
171233
/**
172234
* Resolve with an object with info about a font built with the parameters provided by
173235
* the user. Rejects if the parameters are falsy or the font could not be created.

0 commit comments

Comments
 (0)