Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 18 additions & 35 deletions packages/react-native/Libraries/Text/Text/RCTTextShadowView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -405,28 +405,13 @@ - (CGFloat)lastBaselineForSize:(CGSize)size
[attributedText enumerateAttribute:NSFontAttributeName
inRange:NSMakeRange(0, attributedText.length)
options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
usingBlock:^(UIFont *font, NSRange range, __unused BOOL *stop) {
if (maximumDescender > font.descender) {
maximumDescender = font.descender;
}
}];

// Account for stroke width in baseline calculation
__block CGFloat strokeWidth = 0;
[attributedText enumerateAttribute:@"RCTTextStrokeWidth"
inRange:NSMakeRange(0, attributedText.length)
options:0
usingBlock:^(id value, NSRange range, BOOL *stop) {
if (value && [value isKindOfClass:[NSNumber class]]) {
CGFloat width = [value floatValue];
if (width > 0) {
strokeWidth = MAX(strokeWidth, width);
*stop = YES;
}
}
}];
usingBlock:^(UIFont *font, NSRange range, __unused BOOL *stop) {
if (maximumDescender > font.descender) {
maximumDescender = font.descender;
}
}];

return size.height + maximumDescender + strokeWidth;
return size.height + maximumDescender;
}

static YGSize RCTTextShadowViewMeasure(
Expand Down Expand Up @@ -463,29 +448,27 @@ static YGSize RCTTextShadowViewMeasure(
inRange:NSMakeRange(0, textStorage.length)
options:0
usingBlock:^(id value, NSRange range, BOOL *stop) {
if (value && [value isKindOfClass:[NSNumber class]]) {
CGFloat width = [value floatValue];
if (width > 0) {
strokeWidth = MAX(strokeWidth, width);
*stop = YES;
}
}
}];
if (value && [value isKindOfClass:[NSNumber class]]) {
CGFloat width = [value floatValue];
if (width > 0) {
strokeWidth = MAX(strokeWidth, width);
*stop = YES;
}
}
}];

if (strokeWidth > 0) {
size.width += strokeWidth;
size.height += strokeWidth;
}

size = (CGSize){
MIN(RCTCeilPixelValue(size.width), maximumSize.width), MIN(RCTCeilPixelValue(size.height), maximumSize.height)};
size = (CGSize){MIN(RCTCeilPixelValue(size.width), maximumSize.width),
MIN(RCTCeilPixelValue(size.height), maximumSize.height)};

// Adding epsilon value illuminates problems with converting values from
// `double` to `float`, and then rounding them to pixel grid in Yoga.
CGFloat epsilon = 0.001;
return (YGSize){
RCTYogaFloatFromCoreGraphicsFloat(size.width + epsilon),
RCTYogaFloatFromCoreGraphicsFloat(size.height + epsilon)};
return (YGSize){RCTYogaFloatFromCoreGraphicsFloat(size.width + epsilon),
RCTYogaFloatFromCoreGraphicsFloat(size.height + epsilon)};
}

static float RCTTextShadowViewBaseline(YGNodeConstRef node, const float width, const float height)
Expand Down
42 changes: 22 additions & 20 deletions packages/react-native/Libraries/Text/Text/RCTTextView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -131,21 +131,23 @@ - (void)drawRect:(CGRect)rect
inRange:characterRange
options:0
usingBlock:^(id value, NSRange range, BOOL *stop) {
if (value && [value isKindOfClass:[NSNumber class]]) {
CGFloat width = [value floatValue];
if (width > 0) {
hasStroke = YES;
strokeWidth = width;
strokeColor = [_textStorage attribute:@"RCTTextStrokeColor" atIndex:range.location effectiveRange:NULL];

if (strokeColor) {
CGFloat r, g, b, a;
[strokeColor getRed:&r green:&g blue:&b alpha:&a];
}
*stop = YES;
}
}
}];
if (value && [value isKindOfClass:[NSNumber class]]) {
CGFloat width = [value floatValue];
if (width > 0) {
hasStroke = YES;
strokeWidth = width;
strokeColor = [_textStorage attribute:@"RCTTextStrokeColor"
atIndex:range.location
effectiveRange:NULL];

if (strokeColor) {
CGFloat r, g, b, a;
[strokeColor getRed:&r green:&g blue:&b alpha:&a];
}
*stop = YES;
}
}
}];

if (hasStroke && strokeColor) {
CGContextRef context = UIGraphicsGetCurrentContext();
Expand All @@ -161,12 +163,11 @@ - (void)drawRect:(CGRect)rect
CGContextSetTextDrawingMode(context, kCGTextStroke);

NSMutableAttributedString *strokeText = [_textStorage mutableCopy];
[strokeText addAttribute:NSForegroundColorAttributeName
value:strokeColor
range:characterRange];
[strokeText addAttribute:NSForegroundColorAttributeName value:strokeColor range:characterRange];

CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, _contentFrame.origin.x + strokeInset, self.bounds.size.height - _contentFrame.origin.y + strokeInset);
CGContextTranslateCTM(
context, _contentFrame.origin.x + strokeInset, self.bounds.size.height - _contentFrame.origin.y);
CGContextScaleCTM(context, 1.0, -1.0);

CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)strokeText);
Expand All @@ -184,7 +185,8 @@ - (void)drawRect:(CGRect)rect
CGContextSetTextDrawingMode(context, kCGTextFill);

CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, _contentFrame.origin.x + strokeInset, self.bounds.size.height - _contentFrame.origin.y + strokeInset);
CGContextTranslateCTM(
context, _contentFrame.origin.x + strokeInset, self.bounds.size.height - _contentFrame.origin.y);
CGContextScaleCTM(context, 1.0, -1.0);

framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)_textStorage);
Expand Down
Loading