Skip to content

Commit afc76ac

Browse files
author
aMarCruz
committed
add lineInfoForLine feature (iOS)
1 parent 805714c commit afc76ac

File tree

1 file changed

+79
-19
lines changed

1 file changed

+79
-19
lines changed

ios/RNTextSize.m

Lines changed: 79 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,6 @@ static inline CGFloat CGFloatValueFrom(NSNumber * _Nullable num) {
2929
#endif
3030
}
3131

32-
#if CGFLOAT_IS_DOUBLE
33-
#define CGRound round
34-
#else
35-
#define CGRound roundf
36-
#endif
37-
3832
#define A_SIZE(x) (sizeof (x)/sizeof (x)[0])
3933

4034
/*
@@ -123,25 +117,31 @@ - (dispatch_queue_t)methodQueue {
123117
const CGFloat epsilon = 0.001;
124118
const CGFloat width = MIN(RCTCeilPixelValue(size.width + epsilon), maxSize.width);
125119
const CGFloat height = MIN(RCTCeilPixelValue(size.height + epsilon), maxSize.height);
126-
const CGFloat lineCount = CGRound(size.height / (font.lineHeight + font.leading));
120+
const NSInteger lineCount = [self getLineCount:layoutManager];
121+
122+
NSMutableDictionary *result = [[NSMutableDictionary alloc]
123+
initWithObjectsAndKeys:@(width), @"width",
124+
@(height), @"height",
125+
@(lineCount), @"lineCount",
126+
nil];
127127

128128
if ([options[@"usePreciseWidth"] boolValue]) {
129129
const CGFloat lastIndex = layoutManager.numberOfGlyphs - 1;
130130
const CGSize lastSize = [layoutManager lineFragmentUsedRectForGlyphAtIndex:lastIndex
131131
effectiveRange:nil].size;
132-
resolve(@{
133-
@"width": @(width),
134-
@"height": @(height),
135-
@"lastLineWidth": @(lastSize.width),
136-
@"lineCount": @(lineCount),
137-
});
138-
} else {
139-
resolve(@{
140-
@"width": @(width),
141-
@"height": @(height),
142-
@"lineCount": @(lineCount),
143-
});
132+
[result setValue:@(lastSize.width) forKey:@"lastLineWidth"];
144133
}
134+
135+
const CGFloat optLine = CGFloatValueFrom(options[@"lineInfoForLine"]);
136+
if (!isnan(optLine) && optLine >= 0) {
137+
const NSInteger line = MIN((NSInteger) optLine, lineCount);
138+
NSDictionary *lineInfo = [self getLineInfo:layoutManager str:text lineNo:line];
139+
if (lineInfo) {
140+
[result setValue:lineInfo forKey:@"lineInfo"];
141+
}
142+
}
143+
144+
resolve(result);
145145
}
146146

147147
/**
@@ -371,6 +371,66 @@ - (dispatch_queue_t)methodQueue {
371371
// ============================================================================
372372
//
373373

374+
/**
375+
* Get extended info for a given line number.
376+
* @since v2.1.0
377+
*/
378+
- (NSInteger)getLineCount:(NSLayoutManager *)layoutManager {
379+
NSRange lineRange;
380+
NSUInteger glyphCount = layoutManager.numberOfGlyphs;
381+
NSInteger lineCount = 0;
382+
383+
for (NSUInteger index = 0; index < glyphCount; lineCount++) {
384+
[layoutManager
385+
lineFragmentUsedRectForGlyphAtIndex:index effectiveRange:&lineRange withoutAdditionalLayout:YES];
386+
index = NSMaxRange(lineRange);
387+
}
388+
389+
return lineCount;
390+
}
391+
392+
/**
393+
* Get extended info for a given line number.
394+
* @since v2.1.0
395+
*/
396+
- (NSDictionary *)getLineInfo:(NSLayoutManager *)layoutManager str:(NSString *)str lineNo:(NSInteger)line {
397+
CGRect lineRect = CGRectZero;
398+
NSRange lineRange;
399+
NSUInteger glyphCount = layoutManager.numberOfGlyphs;
400+
NSInteger lineCount = 0;
401+
402+
for (NSUInteger index = 0; index < glyphCount; lineCount++) {
403+
lineRect = [layoutManager
404+
lineFragmentUsedRectForGlyphAtIndex:index
405+
effectiveRange:&lineRange
406+
withoutAdditionalLayout:YES];
407+
index = NSMaxRange(lineRange);
408+
409+
if (line == lineCount) {
410+
NSCharacterSet *ws = NSCharacterSet.whitespaceAndNewlineCharacterSet;
411+
NSRange charRange = [layoutManager characterRangeForGlyphRange:lineRange actualGlyphRange:nil];
412+
NSUInteger start = charRange.location;
413+
index = NSMaxRange(charRange);
414+
/*
415+
Get the trimmed range of chars for the glyph range, to be consistent
416+
w/android, but the width here will include the trailing whitespace.
417+
*/
418+
while (index > start && [ws characterIsMember:[str characterAtIndex:index - 1]]) {
419+
index--;
420+
}
421+
return @{
422+
@"line": @(line),
423+
@"start": @(start),
424+
@"end": @(index),
425+
@"bottom": @(lineRect.origin.y + lineRect.size.height),
426+
@"width": @(lineRect.size.width)
427+
};
428+
}
429+
}
430+
431+
return nil;
432+
}
433+
374434
/**
375435
* Create a scaled font based on the given specs.
376436
*

0 commit comments

Comments
 (0)