mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-05-26 10:45:32 +08:00
Summary: ran `find js/react-native-github/ReactCommon | xargs arc lint -a` Reviewed By: fkgozali Differential Revision: D12902865 fbshipit-source-id: 9c68c0f7e28893e76df966ad4110299e89895454
136 lines
4.2 KiB
Objective-C
136 lines
4.2 KiB
Objective-C
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#import "NSTextStorage+FontScaling.h"
|
|
|
|
typedef NS_OPTIONS(NSInteger, RCTTextSizeComparisonOptions) {
|
|
RCTTextSizeComparisonSmaller = 1 << 0,
|
|
RCTTextSizeComparisonLarger = 1 << 1,
|
|
RCTTextSizeComparisonWithinRange = 1 << 2,
|
|
};
|
|
|
|
@implementation NSTextStorage (FontScaling)
|
|
|
|
- (void)scaleFontSizeToFitSize:(CGSize)size
|
|
minimumFontSize:(CGFloat)minimumFontSize
|
|
maximumFontSize:(CGFloat)maximumFontSize {
|
|
CGFloat bottomRatio = 1.0 / 128.0;
|
|
CGFloat topRatio = 128.0;
|
|
CGFloat ratio = 1.0;
|
|
|
|
NSAttributedString *originalAttributedString = [self copy];
|
|
|
|
CGFloat lastRatioWhichFits = 0.02;
|
|
|
|
while (true) {
|
|
[self scaleFontSizeWithRatio:ratio
|
|
minimumFontSize:minimumFontSize
|
|
maximumFontSize:maximumFontSize];
|
|
|
|
RCTTextSizeComparisonOptions comparsion = [self compareToSize:size
|
|
thresholdRatio:0.01];
|
|
|
|
if ((comparsion & RCTTextSizeComparisonWithinRange) &&
|
|
(comparsion & RCTTextSizeComparisonSmaller)) {
|
|
return;
|
|
} else if (comparsion & RCTTextSizeComparisonSmaller) {
|
|
bottomRatio = ratio;
|
|
lastRatioWhichFits = ratio;
|
|
} else {
|
|
topRatio = ratio;
|
|
}
|
|
|
|
ratio = (topRatio + bottomRatio) / 2.0;
|
|
|
|
CGFloat kRatioThreshold = 0.005;
|
|
if (ABS(topRatio - bottomRatio) < kRatioThreshold ||
|
|
ABS(topRatio - ratio) < kRatioThreshold ||
|
|
ABS(bottomRatio - ratio) < kRatioThreshold) {
|
|
[self replaceCharactersInRange:(NSRange){0, self.length}
|
|
withAttributedString:originalAttributedString];
|
|
|
|
[self scaleFontSizeWithRatio:lastRatioWhichFits
|
|
minimumFontSize:minimumFontSize
|
|
maximumFontSize:maximumFontSize];
|
|
return;
|
|
}
|
|
|
|
[self replaceCharactersInRange:(NSRange){0, self.length}
|
|
withAttributedString:originalAttributedString];
|
|
}
|
|
}
|
|
|
|
- (RCTTextSizeComparisonOptions)compareToSize:(CGSize)size
|
|
thresholdRatio:(CGFloat)thresholdRatio {
|
|
NSLayoutManager *layoutManager = self.layoutManagers.firstObject;
|
|
NSTextContainer *textContainer = layoutManager.textContainers.firstObject;
|
|
|
|
[layoutManager ensureLayoutForTextContainer:textContainer];
|
|
|
|
// Does it fit the text container?
|
|
NSRange glyphRange = [layoutManager glyphRangeForTextContainer:textContainer];
|
|
NSRange truncatedGlyphRange = [layoutManager
|
|
truncatedGlyphRangeInLineFragmentForGlyphAtIndex:glyphRange.length - 1];
|
|
|
|
if (truncatedGlyphRange.location != NSNotFound) {
|
|
return RCTTextSizeComparisonLarger;
|
|
}
|
|
|
|
CGSize measuredSize =
|
|
[layoutManager usedRectForTextContainer:textContainer].size;
|
|
|
|
// Does it fit the size?
|
|
BOOL fitsSize =
|
|
size.width >= measuredSize.width && size.height >= measuredSize.height;
|
|
|
|
CGSize thresholdSize = (CGSize){
|
|
size.width * thresholdRatio,
|
|
size.height * thresholdRatio,
|
|
};
|
|
|
|
RCTTextSizeComparisonOptions result = 0;
|
|
|
|
result |=
|
|
(fitsSize) ? RCTTextSizeComparisonSmaller : RCTTextSizeComparisonLarger;
|
|
|
|
if (ABS(measuredSize.width - size.width) < thresholdSize.width) {
|
|
result = result | RCTTextSizeComparisonWithinRange;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
- (void)scaleFontSizeWithRatio:(CGFloat)ratio
|
|
minimumFontSize:(CGFloat)minimumFontSize
|
|
maximumFontSize:(CGFloat)maximumFontSize {
|
|
[self beginEditing];
|
|
|
|
[self
|
|
enumerateAttribute:NSFontAttributeName
|
|
inRange:(NSRange){0, self.length}
|
|
options:
|
|
NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
|
|
usingBlock:^(
|
|
UIFont *_Nullable font, NSRange range, BOOL *_Nonnull stop) {
|
|
if (!font) {
|
|
return;
|
|
}
|
|
|
|
CGFloat fontSize =
|
|
MAX(MIN(font.pointSize * ratio, maximumFontSize),
|
|
minimumFontSize);
|
|
|
|
[self addAttribute:NSFontAttributeName
|
|
value:[font fontWithSize:fontSize]
|
|
range:range];
|
|
}];
|
|
|
|
[self endEditing];
|
|
}
|
|
|
|
@end
|