Skip to content

Commit

Permalink
Text: send metrics after rendering (iOS)
Browse files Browse the repository at this point in the history
Summary: This adds a callback for <Text> to get metrics about the rendered text. It's divided by line but that could be changed to "fragments" (which makes more sense for multi-lingual). Right now by line is convenient as you frequently want to know where the first and last line end (though we could make this work with fragments I suppose).

Reviewed By: shergin

Differential Revision: D9440914

fbshipit-source-id: bb011bb7a52438380d3f604ffe7019b98c18d978
  • Loading branch information
Mehdi Mulani authored and facebook-github-bot committed Aug 24, 2018
1 parent 1f96ff6 commit 64a5253
Show file tree
Hide file tree
Showing 6 changed files with 372 additions and 1 deletion.
6 changes: 6 additions & 0 deletions Libraries/Text/Text.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ const viewConfig = {
adjustsFontSizeToFit: true,
minimumFontScale: true,
textBreakStrategy: true,
onTextLayout: true,
},
directEventTypes: {
topTextLayout: {
registrationName: 'onTextLayout',
},
},
uiViewClassName: 'RCTText',
};
Expand Down
1 change: 1 addition & 0 deletions Libraries/Text/Text/RCTTextShadowView.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, assign) NSLineBreakMode lineBreakMode;
@property (nonatomic, assign) BOOL adjustsFontSizeToFit;
@property (nonatomic, assign) CGFloat minimumFontScale;
@property (nonatomic, copy) RCTDirectEventBlock onTextLayout;

- (void)uiManagerWillPerformMounting;

Expand Down
29 changes: 29 additions & 0 deletions Libraries/Text/Text/RCTTextShadowView.m
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,35 @@ - (void)layoutSubviewsWithContext:(RCTLayoutContext)layoutContext
[shadowView layoutWithMetrics:localLayoutMetrics layoutContext:localLayoutContext];
}
];


if (_onTextLayout) {
NSMutableArray *lineData = [NSMutableArray new];
[layoutManager
enumerateLineFragmentsForGlyphRange:glyphRange
usingBlock:^(CGRect overallRect, CGRect usedRect, NSTextContainer * _Nonnull usedTextContainer, NSRange lineGlyphRange, BOOL * _Nonnull stop) {
NSRange range = [layoutManager characterRangeForGlyphRange:lineGlyphRange actualGlyphRange:nil];
NSString *renderedString = [textStorage.string substringWithRange:range];
UIFont *font = [[textStorage attributedSubstringFromRange:range] attribute:NSFontAttributeName atIndex:0 effectiveRange:nil];
[lineData addObject:
@{
@"text": renderedString,
@"x": @(usedRect.origin.x),
@"y": @(usedRect.origin.y),
@"width": @(usedRect.size.width),
@"height": @(usedRect.size.height),
@"descender": @(-font.descender),
@"capHeight": @(font.capHeight),
@"ascender": @(font.ascender),
@"xHeight": @(font.xHeight),
}];
}];
NSDictionary *payload =
@{
@"lines": lineData,
};
_onTextLayout(payload);
}
}

- (CGFloat)lastBaselineForSize:(CGSize)size
Expand Down
2 changes: 2 additions & 0 deletions Libraries/Text/Text/RCTTextView.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/

#import <React/RCTComponent.h>

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN
Expand Down
2 changes: 2 additions & 0 deletions Libraries/Text/Text/RCTTextViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ @implementation RCTTextViewManager
RCT_REMAP_SHADOW_PROPERTY(adjustsFontSizeToFit, adjustsFontSizeToFit, BOOL)
RCT_REMAP_SHADOW_PROPERTY(minimumFontScale, minimumFontScale, CGFloat)

RCT_EXPORT_SHADOW_PROPERTY(onTextLayout, RCTDirectEventBlock)

RCT_EXPORT_VIEW_PROPERTY(selectable, BOOL)

- (void)setBridge:(RCTBridge *)bridge
Expand Down
Loading

0 comments on commit 64a5253

Please sign in to comment.