react-native-macos/Libraries/Text/RCTTextAttributes.m

313 строки
12 KiB
Mathematica
Исходник Обычный вид История

/**
* 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.
*/
CocoaPods frameworks compatibility: Step 2 (#25619) Summary: This is my proposal for fixing `use_frameworks!` compatibility without breaking all `<React/*>` imports I outlined in https://github.com/facebook/react-native/pull/25393#issuecomment-508457700. If accepted, it will fix https://github.com/facebook/react-native/issues/25349. It builds on the changes I made in https://github.com/facebook/react-native/pull/25496 by ensuring each podspec has a unique value for `header_dir` so that framework imports do not conflict. Every podspec which should be included in the `<React/*>` namespace now includes it's headers from `React-Core.podspec`. The following pods can still be imported with `<React/*>` and so should not have breaking changes: `React-ART`,`React-DevSupport`, `React-CoreModules`, `React-RCTActionSheet`, `React-RCTAnimation`, `React-RCTBlob`, `React-RCTImage`, `React-RCTLinking`, `React-RCTNetwork`, `React-RCTPushNotification`, `React-RCTSettings`, `React-RCTText`, `React-RCTSettings`, `React-RCTVibration`, `React-RCTWebSocket` . There are still a few breaking changes which I hope will be acceptable: - `React-Core.podspec` has been moved to the root of the project. Any `Podfile` that references it will need to update the path. - ~~`React-turbomodule-core`'s headers now live under `<turbomodule/*>`~~ Replaced by https://github.com/facebook/react-native/pull/25619#issuecomment-511091823. - ~~`React-turbomodulesamples`'s headers now live under `<turbomodulesamples/*>`~~ Replaced by https://github.com/facebook/react-native/pull/25619#issuecomment-511091823. - ~~`React-TypeSaferty`'s headers now live under `<TypeSafety/*>`~~ Replaced by https://github.com/facebook/react-native/pull/25619#issuecomment-511040967. - ~~`React-jscallinvoker`'s headers now live under `<jscallinvoker/*>`~~ Replaced by https://github.com/facebook/react-native/pull/25619#issuecomment-511091823. - Each podspec now uses `s.static_framework = true`. This means that a minimum of CocoaPods 1.5 ([released in April 2018](http://blog.cocoapods.org/CocoaPods-1.5.0/)) is now required. This is needed so that the ` __has_include` conditions can still work when frameworks are enabled. Still to do: - ~~Including `React-turbomodule-core` with `use_frameworks!` enabled causes the C++ import failures we saw in https://github.com/facebook/react-native/issues/25349. I'm sure it will be possible to fix this but I need to dig deeper (perhaps a custom modulemap would be needed).~~ Addressed by https://github.com/facebook/react-native/pull/25619/commits/33573511f02f3502a28bad48e085e9a4b8608302. - I haven't got Fabric working yet. I wonder if it would be acceptable to move Fabric out of the `<React/*>` namespace since it is new? � ## Changelog [iOS] [Fixed] - Fixed compatibility with CocoaPods frameworks. Pull Request resolved: https://github.com/facebook/react-native/pull/25619 Test Plan: ### FB ``` buck build catalyst ``` ### Sample Project Everything should work exactly as before, where `use_frameworks!` is not in `Podfile`s. I have a branch on my [sample project](https://github.com/jtreanor/react-native-cocoapods-frameworks) here which has `use_frameworks!` in its `Podfile` to demonstrate this is fixed. You can see that it works with these steps: 1. `git clone git@github.com:jtreanor/react-native-cocoapods-frameworks.git` 2. `git checkout fix-frameworks-subspecs` 3. `cd ios && pod install` 4. `cd .. && react-native run-ios` The sample app will build and run successfully. To see that it still works without frameworks, remove `use_frameworks!` from the `Podfile` and do steps 3 and 4 again. ### RNTesterPods `RNTesterPodsPods` can now work with or without `use_frameworks!`. 1. Go to the `RNTester` directory and run `pod install`. 2. Run the tests in `RNTesterPods.xcworkspace` to see that everything still works fine. 3. Uncomment the `use_frameworks!` line at the top of `RNTester/Podfile` and run `pod install` again. 4. Run the tests again and see that it still works with frameworks enabled. Reviewed By: PeteTheHeat Differential Revision: D16465247 Pulled By: PeteTheHeat fbshipit-source-id: cad837e9cced06d30cc5b372af1c65c7780b9e7a
2019-07-25 08:26:42 +03:00
#import <React/RCTTextAttributes.h>
#import <React/RCTAssert.h>
#import <React/RCTFont.h>
#import <React/RCTLog.h>
NSString *const RCTTextAttributesIsHighlightedAttributeName = @"RCTTextAttributesIsHighlightedAttributeName";
NSString *const RCTTextAttributesTagAttributeName = @"RCTTextAttributesTagAttributeName";
@implementation RCTTextAttributes
- (instancetype)init
{
if (self = [super init]) {
_fontSize = NAN;
_letterSpacing = NAN;
Adds _lineHeight = NAN; to RCTTextAttributes Summary: <!-- Thank you for sending the PR! We appreciate you spending the time to work on these changes. Help us understand your motivation by explaining why you decided to make this change. You can learn more about contributing to React Native here: http://facebook.github.io/react-native/docs/contributing.html Happy contributing! --> On iOS, when the parent Text contains the `lineHeight` style prop, and the children are also Text components they don't inherit the lineHeight prop. This is for **iOS** only. Create a react-native project with React Native 0.54.0 or 0.54.1 and change the app to: ```js import React, { Component } from 'react'; import { StyleSheet, Text, View } from 'react-native'; type Props = {}; export default class App extends Component<Props> { render() { return ( <View style={styles.container}> <Text style={{ fontWeight: 'bold', lineHeight: 40 }}> <Text style={{ color: 'orange' }}>I am bold and orange, </Text> <Text style={{ color: 'red' }}>I am bold and red, </Text> <Text style={{ color: 'blue' }}>I am bold and blue, </Text> <Text style={{ color: 'purple' }}>I am bold and purple, </Text> <Text style={{ color: 'yellow' }}>I am bold and yellow, </Text> <Text style={{ color: 'pink' }}>I am bold and pink</Text> </Text> </View> ); } } const styles = StyleSheet.create({ container: { backgroundColor: 'black', flex: 1, justifyContent: 'center', padding: 50, }, }); ``` It displays: ![iphone - 2018-03-12 at 21 51 53](https://user-images.githubusercontent.com/480605/37308941-b56f082e-263f-11e8-9c23-892f77077169.png) But should look like: ![iphone - 2018-03-12 at 21 48 15](https://user-images.githubusercontent.com/480605/37308784-4efaddf2-263f-11e8-992b-ee0b6bb9a97b.png) New &lt;Text> iOS https://github.com/facebook/react-native/commit/2716f53 <!-- Help reviewers and the release process by writing your own release notes **INTERNAL and MINOR tagged notes will not be included in the next version's final release notes.** CATEGORY [----------] TYPE [ CLI ] [-------------] LOCATION [ DOCS ] [ BREAKING ] [-------------] [ GENERAL ] [ BUGFIX ] [-{Component}-] [ INTERNAL ] [ ENHANCEMENT ] [ {File} ] [ IOS ] [ FEATURE ] [ {Directory} ] |-----------| [ ANDROID ] [ MINOR ] [ {Framework} ] - | {Message} | [----------] [-------------] [-------------] |-----------| [CATEGORY] [TYPE] [LOCATION] - MESSAGE EXAMPLES: [IOS] [BREAKING] [FlatList] - Change a thing that breaks other things [ANDROID] [BUGFIX] [TextInput] - Did a thing to TextInput [CLI] [FEATURE] [local-cli/info/info.js] - CLI easier to do things with [DOCS] [BUGFIX] [GettingStarted.md] - Accidentally a thing/word [GENERAL] [ENHANCEMENT] [Yoga] - Added new yoga thing/position [INTERNAL] [FEATURE] [./scripts] - Added thing to script that nobody will see --> [IOS] [MINOR] [Text] - Inherit lineheight Closes https://github.com/facebook/react-native/pull/18340 Differential Revision: D7276655 Pulled By: shergin fbshipit-source-id: 0fe26536bb74da77be8405911fc699a622bc0b2f
2018-03-14 23:04:41 +03:00
_lineHeight = NAN;
_textDecorationStyle = NSUnderlineStyleSingle;
_fontSizeMultiplier = NAN;
iOS: Add a maxFontSizeMultiplier prop to <Text> and <TextInput> (#20915) Summary: **Motivation** Whenever a user changes the system font size to its maximum allowable setting, React Native apps that allow font scaling can become unusable because the text gets too big. Experimenting with a native app like iMessage on iOS, the font size used for non-body text (e.g. header, navigational elements) is capped while the body text (e.g. text in the message bubbles) is allowed to grow. This PR introduces a new prop on `<Text>` and `<TextInput>` called `maxFontSizeMultiplier`. This enables devs to set the maximum allowed text scale factor on a Text/TextInput. The default is 0 which means no limit. Another PR will add this feature to Android. **Test Plan** I created a test app which utilizes all categories of values of `maxFontSizeMultiplier`: - `undefined`: inherit from parent - `0`: no limit - `1`, `1.2`: fixed limits I tried this with `Text`, `TextInput` with `value`, and `TextInput` with children. For `Text`, I also verified that nesting works properly (if a child `Text` doesn't specify `maxFontSizeMultiplier`, it inherits it from its parent). Lastly, we've been using a version of this in Skype for several months. **Release Notes** [GENERAL] [ENHANCEMENT] [Text/TextInput] - Added maxFontSizeMultiplier prop to prevent some text from getting unusably large as user increases OS's font scale setting (iOS) Adam Comella Microsoft Corp. Pull Request resolved: https://github.com/facebook/react-native/pull/20915 Differential Revision: D9646739 Pulled By: shergin fbshipit-source-id: c823f59c1e342c22d6297b88b2cb11c5a1f10310
2018-09-05 03:33:06 +03:00
_maxFontSizeMultiplier = NAN;
_alignment = NSTextAlignmentNatural;
_baseWritingDirection = NSWritingDirectionNatural;
_textShadowRadius = NAN;
_opacity = NAN;
iOS textTransform style support Summary: Issue [#2088](https://github.com/facebook/react-native/issues/2088). The basic desire is to have a declarative mechanism to transform text content to uppercase or lowercase or titlecase ("capitalized"). My test plan involves having added a test-case to the RNTester app within the `<Text>` component area. I then manually verified that the rendered content met my expectation. Here is the markup that exercises my enhancement: ``` <View> <Text style={{ textTransform: 'uppercase'}}> This text should be uppercased. </Text> <Text style={{ textTransform: 'lowercase'}}> This TEXT SHOULD be lowercased. </Text> <Text style={{ textTransform: 'capitalize'}}> This text should be CAPITALIZED. </Text> <Text style={{ textTransform: 'capitalize'}}> Mixed:{' '} <Text style={{ textTransform: 'uppercase'}}> uppercase{' '} </Text> <Text style={{ textTransform: 'lowercase'}}> LoWeRcAsE{' '} </Text> <Text style={{ textTransform: 'capitalize'}}> capitalize each word </Text> </Text> </View> ``` And here is a screenshot of the result: ![screen shot 2018-03-14 at 3 01 02 pm](https://user-images.githubusercontent.com/575821/37433772-7abe7fa0-279a-11e8-9ec9-fb3aa1952dad.png) [Website Documentation PR](https://github.com/facebook/react-native-website/pull/254) https://github.com/facebook/react-native-website/pull/254 [IOS] [ENHANCEMENT] [Text] - added textTransform style property enabling declarative casing transformations Closes https://github.com/facebook/react-native/pull/18387 Differential Revision: D7583315 Pulled By: shergin fbshipit-source-id: a5d22aea2aa4f494b7b25a055abe64799ccbaa79
2018-04-16 18:59:26 +03:00
_textTransform = RCTTextTransformUndefined;
}
return self;
}
- (void)applyTextAttributes:(RCTTextAttributes *)textAttributes
{
// Note: All lines marked with `*` does not use explicit/correct rules to compare old and new values because
// their types do not have special designated value representing undefined/unspecified/inherit meaning.
// We will address this in the future.
// Color
_foregroundColor = textAttributes->_foregroundColor ?: _foregroundColor;
_backgroundColor = textAttributes->_backgroundColor ?: _backgroundColor;
_opacity = !isnan(textAttributes->_opacity) ? (isnan(_opacity) ? 1.0 : _opacity) * textAttributes->_opacity : _opacity;
// Font
_fontFamily = textAttributes->_fontFamily ?: _fontFamily;
_fontSize = !isnan(textAttributes->_fontSize) ? textAttributes->_fontSize : _fontSize;
_fontSizeMultiplier = !isnan(textAttributes->_fontSizeMultiplier) ? textAttributes->_fontSizeMultiplier : _fontSizeMultiplier;
iOS: Add a maxFontSizeMultiplier prop to <Text> and <TextInput> (#20915) Summary: **Motivation** Whenever a user changes the system font size to its maximum allowable setting, React Native apps that allow font scaling can become unusable because the text gets too big. Experimenting with a native app like iMessage on iOS, the font size used for non-body text (e.g. header, navigational elements) is capped while the body text (e.g. text in the message bubbles) is allowed to grow. This PR introduces a new prop on `<Text>` and `<TextInput>` called `maxFontSizeMultiplier`. This enables devs to set the maximum allowed text scale factor on a Text/TextInput. The default is 0 which means no limit. Another PR will add this feature to Android. **Test Plan** I created a test app which utilizes all categories of values of `maxFontSizeMultiplier`: - `undefined`: inherit from parent - `0`: no limit - `1`, `1.2`: fixed limits I tried this with `Text`, `TextInput` with `value`, and `TextInput` with children. For `Text`, I also verified that nesting works properly (if a child `Text` doesn't specify `maxFontSizeMultiplier`, it inherits it from its parent). Lastly, we've been using a version of this in Skype for several months. **Release Notes** [GENERAL] [ENHANCEMENT] [Text/TextInput] - Added maxFontSizeMultiplier prop to prevent some text from getting unusably large as user increases OS's font scale setting (iOS) Adam Comella Microsoft Corp. Pull Request resolved: https://github.com/facebook/react-native/pull/20915 Differential Revision: D9646739 Pulled By: shergin fbshipit-source-id: c823f59c1e342c22d6297b88b2cb11c5a1f10310
2018-09-05 03:33:06 +03:00
_maxFontSizeMultiplier = !isnan(textAttributes->_maxFontSizeMultiplier) ? textAttributes->_maxFontSizeMultiplier : _maxFontSizeMultiplier;
_fontWeight = textAttributes->_fontWeight ?: _fontWeight;
_fontStyle = textAttributes->_fontStyle ?: _fontStyle;
_fontVariant = textAttributes->_fontVariant ?: _fontVariant;
_allowFontScaling = textAttributes->_allowFontScaling || _allowFontScaling; // *
_letterSpacing = !isnan(textAttributes->_letterSpacing) ? textAttributes->_letterSpacing : _letterSpacing;
// Paragraph Styles
_lineHeight = !isnan(textAttributes->_lineHeight) ? textAttributes->_lineHeight : _lineHeight;
_alignment = textAttributes->_alignment != NSTextAlignmentNatural ? textAttributes->_alignment : _alignment; // *
_baseWritingDirection = textAttributes->_baseWritingDirection != NSWritingDirectionNatural ? textAttributes->_baseWritingDirection : _baseWritingDirection; // *
// Decoration
_textDecorationColor = textAttributes->_textDecorationColor ?: _textDecorationColor;
_textDecorationStyle = textAttributes->_textDecorationStyle != NSUnderlineStyleSingle ? textAttributes->_textDecorationStyle : _textDecorationStyle; // *
_textDecorationLine = textAttributes->_textDecorationLine != RCTTextDecorationLineTypeNone ? textAttributes->_textDecorationLine : _textDecorationLine; // *
// Shadow
_textShadowOffset = !CGSizeEqualToSize(textAttributes->_textShadowOffset, CGSizeZero) ? textAttributes->_textShadowOffset : _textShadowOffset; // *
_textShadowRadius = !isnan(textAttributes->_textShadowRadius) ? textAttributes->_textShadowRadius : _textShadowRadius;
_textShadowColor = textAttributes->_textShadowColor ?: _textShadowColor;
// Special
_isHighlighted = textAttributes->_isHighlighted || _isHighlighted; // *
_tag = textAttributes->_tag ?: _tag;
_layoutDirection = textAttributes->_layoutDirection != UIUserInterfaceLayoutDirectionLeftToRight ? textAttributes->_layoutDirection : _layoutDirection;
iOS textTransform style support Summary: Issue [#2088](https://github.com/facebook/react-native/issues/2088). The basic desire is to have a declarative mechanism to transform text content to uppercase or lowercase or titlecase ("capitalized"). My test plan involves having added a test-case to the RNTester app within the `<Text>` component area. I then manually verified that the rendered content met my expectation. Here is the markup that exercises my enhancement: ``` <View> <Text style={{ textTransform: 'uppercase'}}> This text should be uppercased. </Text> <Text style={{ textTransform: 'lowercase'}}> This TEXT SHOULD be lowercased. </Text> <Text style={{ textTransform: 'capitalize'}}> This text should be CAPITALIZED. </Text> <Text style={{ textTransform: 'capitalize'}}> Mixed:{' '} <Text style={{ textTransform: 'uppercase'}}> uppercase{' '} </Text> <Text style={{ textTransform: 'lowercase'}}> LoWeRcAsE{' '} </Text> <Text style={{ textTransform: 'capitalize'}}> capitalize each word </Text> </Text> </View> ``` And here is a screenshot of the result: ![screen shot 2018-03-14 at 3 01 02 pm](https://user-images.githubusercontent.com/575821/37433772-7abe7fa0-279a-11e8-9ec9-fb3aa1952dad.png) [Website Documentation PR](https://github.com/facebook/react-native-website/pull/254) https://github.com/facebook/react-native-website/pull/254 [IOS] [ENHANCEMENT] [Text] - added textTransform style property enabling declarative casing transformations Closes https://github.com/facebook/react-native/pull/18387 Differential Revision: D7583315 Pulled By: shergin fbshipit-source-id: a5d22aea2aa4f494b7b25a055abe64799ccbaa79
2018-04-16 18:59:26 +03:00
_textTransform = textAttributes->_textTransform != RCTTextTransformUndefined ? textAttributes->_textTransform : _textTransform;
}
- (NSParagraphStyle *)effectiveParagraphStyle
{
// Paragraph Style
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
BOOL isParagraphStyleUsed = NO;
if (_alignment != NSTextAlignmentNatural) {
NSTextAlignment alignment = _alignment;
if (_layoutDirection == UIUserInterfaceLayoutDirectionRightToLeft) {
if (alignment == NSTextAlignmentRight) {
alignment = NSTextAlignmentLeft;
} else if (alignment == NSTextAlignmentLeft) {
alignment = NSTextAlignmentRight;
}
}
paragraphStyle.alignment = alignment;
isParagraphStyleUsed = YES;
}
if (_baseWritingDirection != NSWritingDirectionNatural) {
paragraphStyle.baseWritingDirection = _baseWritingDirection;
isParagraphStyleUsed = YES;
}
if (!isnan(_lineHeight)) {
CGFloat lineHeight = _lineHeight * self.effectiveFontSizeMultiplier;
paragraphStyle.minimumLineHeight = lineHeight;
paragraphStyle.maximumLineHeight = lineHeight;
isParagraphStyleUsed = YES;
}
if (isParagraphStyleUsed) {
return [paragraphStyle copy];
}
return nil;
}
- (NSDictionary<NSAttributedStringKey, id> *)effectiveTextAttributes
{
NSMutableDictionary<NSAttributedStringKey, id> *attributes =
[NSMutableDictionary dictionaryWithCapacity:10];
// Font
UIFont *font = self.effectiveFont;
if (font) {
attributes[NSFontAttributeName] = font;
}
// Colors
UIColor *effectiveForegroundColor = self.effectiveForegroundColor;
if (_foregroundColor || !isnan(_opacity)) {
attributes[NSForegroundColorAttributeName] = effectiveForegroundColor;
}
if (_backgroundColor || !isnan(_opacity)) {
attributes[NSBackgroundColorAttributeName] = self.effectiveBackgroundColor;
}
// Kerning
if (!isnan(_letterSpacing)) {
attributes[NSKernAttributeName] = @(_letterSpacing);
}
// Paragraph Style
NSParagraphStyle *paragraphStyle = [self effectiveParagraphStyle];
if (paragraphStyle) {
attributes[NSParagraphStyleAttributeName] = paragraphStyle;
}
// Decoration
BOOL isTextDecorationEnabled = NO;
if (_textDecorationLine == RCTTextDecorationLineTypeUnderline ||
_textDecorationLine == RCTTextDecorationLineTypeUnderlineStrikethrough) {
isTextDecorationEnabled = YES;
attributes[NSUnderlineStyleAttributeName] = @(_textDecorationStyle);
}
if (_textDecorationLine == RCTTextDecorationLineTypeStrikethrough ||
_textDecorationLine == RCTTextDecorationLineTypeUnderlineStrikethrough){
isTextDecorationEnabled = YES;
attributes[NSStrikethroughStyleAttributeName] = @(_textDecorationStyle);
}
if (_textDecorationColor || isTextDecorationEnabled) {
attributes[NSStrikethroughColorAttributeName] = _textDecorationColor ?: effectiveForegroundColor;
attributes[NSUnderlineColorAttributeName] = _textDecorationColor ?: effectiveForegroundColor;
}
// Shadow
if (!isnan(_textShadowRadius)) {
NSShadow *shadow = [NSShadow new];
shadow.shadowOffset = _textShadowOffset;
shadow.shadowBlurRadius = _textShadowRadius;
shadow.shadowColor = _textShadowColor;
attributes[NSShadowAttributeName] = shadow;
}
// Special
if (_isHighlighted) {
attributes[RCTTextAttributesIsHighlightedAttributeName] = @YES;
}
if (_tag) {
attributes[RCTTextAttributesTagAttributeName] = _tag;
}
return [attributes copy];
}
- (UIFont *)effectiveFont
{
// FIXME: RCTFont has thread-safety issues and must be rewritten.
return [RCTFont updateFont:nil
withFamily:_fontFamily
size:@(isnan(_fontSize) ? 0 : _fontSize)
weight:_fontWeight
style:_fontStyle
variant:_fontVariant
scaleMultiplier:self.effectiveFontSizeMultiplier];
}
- (CGFloat)effectiveFontSizeMultiplier
{
iOS: Add a maxFontSizeMultiplier prop to <Text> and <TextInput> (#20915) Summary: **Motivation** Whenever a user changes the system font size to its maximum allowable setting, React Native apps that allow font scaling can become unusable because the text gets too big. Experimenting with a native app like iMessage on iOS, the font size used for non-body text (e.g. header, navigational elements) is capped while the body text (e.g. text in the message bubbles) is allowed to grow. This PR introduces a new prop on `<Text>` and `<TextInput>` called `maxFontSizeMultiplier`. This enables devs to set the maximum allowed text scale factor on a Text/TextInput. The default is 0 which means no limit. Another PR will add this feature to Android. **Test Plan** I created a test app which utilizes all categories of values of `maxFontSizeMultiplier`: - `undefined`: inherit from parent - `0`: no limit - `1`, `1.2`: fixed limits I tried this with `Text`, `TextInput` with `value`, and `TextInput` with children. For `Text`, I also verified that nesting works properly (if a child `Text` doesn't specify `maxFontSizeMultiplier`, it inherits it from its parent). Lastly, we've been using a version of this in Skype for several months. **Release Notes** [GENERAL] [ENHANCEMENT] [Text/TextInput] - Added maxFontSizeMultiplier prop to prevent some text from getting unusably large as user increases OS's font scale setting (iOS) Adam Comella Microsoft Corp. Pull Request resolved: https://github.com/facebook/react-native/pull/20915 Differential Revision: D9646739 Pulled By: shergin fbshipit-source-id: c823f59c1e342c22d6297b88b2cb11c5a1f10310
2018-09-05 03:33:06 +03:00
bool fontScalingEnabled = !RCTHasFontHandlerSet() && _allowFontScaling;
if (fontScalingEnabled) {
CGFloat fontSizeMultiplier = !isnan(_fontSizeMultiplier) ? _fontSizeMultiplier : 1.0;
CGFloat maxFontSizeMultiplier = !isnan(_maxFontSizeMultiplier) ? _maxFontSizeMultiplier : 0.0;
return maxFontSizeMultiplier >= 1.0 ? fminf(maxFontSizeMultiplier, fontSizeMultiplier) : fontSizeMultiplier;
} else {
return 1.0;
}
}
- (UIColor *)effectiveForegroundColor
{
UIColor *effectiveForegroundColor = _foregroundColor ?: [UIColor blackColor];
if (!isnan(_opacity)) {
effectiveForegroundColor = [effectiveForegroundColor colorWithAlphaComponent:CGColorGetAlpha(effectiveForegroundColor.CGColor) * _opacity];
}
return effectiveForegroundColor;
}
- (UIColor *)effectiveBackgroundColor
{
UIColor *effectiveBackgroundColor = _backgroundColor;// ?: [[UIColor whiteColor] colorWithAlphaComponent:0];
if (effectiveBackgroundColor && !isnan(_opacity)) {
effectiveBackgroundColor = [effectiveBackgroundColor colorWithAlphaComponent:CGColorGetAlpha(effectiveBackgroundColor.CGColor) * _opacity];
}
return effectiveBackgroundColor ?: [UIColor clearColor];
}
iOS textTransform style support Summary: Issue [#2088](https://github.com/facebook/react-native/issues/2088). The basic desire is to have a declarative mechanism to transform text content to uppercase or lowercase or titlecase ("capitalized"). My test plan involves having added a test-case to the RNTester app within the `<Text>` component area. I then manually verified that the rendered content met my expectation. Here is the markup that exercises my enhancement: ``` <View> <Text style={{ textTransform: 'uppercase'}}> This text should be uppercased. </Text> <Text style={{ textTransform: 'lowercase'}}> This TEXT SHOULD be lowercased. </Text> <Text style={{ textTransform: 'capitalize'}}> This text should be CAPITALIZED. </Text> <Text style={{ textTransform: 'capitalize'}}> Mixed:{' '} <Text style={{ textTransform: 'uppercase'}}> uppercase{' '} </Text> <Text style={{ textTransform: 'lowercase'}}> LoWeRcAsE{' '} </Text> <Text style={{ textTransform: 'capitalize'}}> capitalize each word </Text> </Text> </View> ``` And here is a screenshot of the result: ![screen shot 2018-03-14 at 3 01 02 pm](https://user-images.githubusercontent.com/575821/37433772-7abe7fa0-279a-11e8-9ec9-fb3aa1952dad.png) [Website Documentation PR](https://github.com/facebook/react-native-website/pull/254) https://github.com/facebook/react-native-website/pull/254 [IOS] [ENHANCEMENT] [Text] - added textTransform style property enabling declarative casing transformations Closes https://github.com/facebook/react-native/pull/18387 Differential Revision: D7583315 Pulled By: shergin fbshipit-source-id: a5d22aea2aa4f494b7b25a055abe64799ccbaa79
2018-04-16 18:59:26 +03:00
- (NSString *)applyTextAttributesToText:(NSString *)text
{
switch (_textTransform) {
case RCTTextTransformUndefined:
case RCTTextTransformNone:
return text;
case RCTTextTransformLowercase:
return [text lowercaseString];
case RCTTextTransformUppercase:
return [text uppercaseString];
case RCTTextTransformCapitalize:
return [text capitalizedString];
}
}
- (RCTTextAttributes *)copyWithZone:(NSZone *)zone
{
RCTTextAttributes *textAttributes = [RCTTextAttributes new];
[textAttributes applyTextAttributes:self];
return textAttributes;
}
#pragma mark - NSObject
- (BOOL)isEqual:(RCTTextAttributes *)textAttributes
{
if (!textAttributes) {
return NO;
}
if (self == textAttributes) {
return YES;
}
#define RCTTextAttributesCompareFloats(a) ((a == textAttributes->a) || (isnan(a) && isnan(textAttributes->a)))
#define RCTTextAttributesCompareSize(a) CGSizeEqualToSize(a, textAttributes->a)
#define RCTTextAttributesCompareObjects(a) ((a == textAttributes->a) || [a isEqual:textAttributes->a])
#define RCTTextAttributesCompareStrings(a) ((a == textAttributes->a) || [a isEqualToString:textAttributes->a])
#define RCTTextAttributesCompareOthers(a) (a == textAttributes->a)
return
RCTTextAttributesCompareObjects(_foregroundColor) &&
RCTTextAttributesCompareObjects(_backgroundColor) &&
RCTTextAttributesCompareFloats(_opacity) &&
// Font
RCTTextAttributesCompareObjects(_fontFamily) &&
RCTTextAttributesCompareFloats(_fontSize) &&
RCTTextAttributesCompareFloats(_fontSizeMultiplier) &&
iOS: Add a maxFontSizeMultiplier prop to <Text> and <TextInput> (#20915) Summary: **Motivation** Whenever a user changes the system font size to its maximum allowable setting, React Native apps that allow font scaling can become unusable because the text gets too big. Experimenting with a native app like iMessage on iOS, the font size used for non-body text (e.g. header, navigational elements) is capped while the body text (e.g. text in the message bubbles) is allowed to grow. This PR introduces a new prop on `<Text>` and `<TextInput>` called `maxFontSizeMultiplier`. This enables devs to set the maximum allowed text scale factor on a Text/TextInput. The default is 0 which means no limit. Another PR will add this feature to Android. **Test Plan** I created a test app which utilizes all categories of values of `maxFontSizeMultiplier`: - `undefined`: inherit from parent - `0`: no limit - `1`, `1.2`: fixed limits I tried this with `Text`, `TextInput` with `value`, and `TextInput` with children. For `Text`, I also verified that nesting works properly (if a child `Text` doesn't specify `maxFontSizeMultiplier`, it inherits it from its parent). Lastly, we've been using a version of this in Skype for several months. **Release Notes** [GENERAL] [ENHANCEMENT] [Text/TextInput] - Added maxFontSizeMultiplier prop to prevent some text from getting unusably large as user increases OS's font scale setting (iOS) Adam Comella Microsoft Corp. Pull Request resolved: https://github.com/facebook/react-native/pull/20915 Differential Revision: D9646739 Pulled By: shergin fbshipit-source-id: c823f59c1e342c22d6297b88b2cb11c5a1f10310
2018-09-05 03:33:06 +03:00
RCTTextAttributesCompareFloats(_maxFontSizeMultiplier) &&
RCTTextAttributesCompareStrings(_fontWeight) &&
RCTTextAttributesCompareObjects(_fontStyle) &&
RCTTextAttributesCompareObjects(_fontVariant) &&
RCTTextAttributesCompareOthers(_allowFontScaling) &&
RCTTextAttributesCompareFloats(_letterSpacing) &&
// Paragraph Styles
RCTTextAttributesCompareFloats(_lineHeight) &&
RCTTextAttributesCompareFloats(_alignment) &&
RCTTextAttributesCompareOthers(_baseWritingDirection) &&
// Decoration
RCTTextAttributesCompareObjects(_textDecorationColor) &&
RCTTextAttributesCompareOthers(_textDecorationStyle) &&
RCTTextAttributesCompareOthers(_textDecorationLine) &&
// Shadow
RCTTextAttributesCompareSize(_textShadowOffset) &&
RCTTextAttributesCompareFloats(_textShadowRadius) &&
RCTTextAttributesCompareObjects(_textShadowColor) &&
// Special
RCTTextAttributesCompareOthers(_isHighlighted) &&
RCTTextAttributesCompareObjects(_tag) &&
iOS textTransform style support Summary: Issue [#2088](https://github.com/facebook/react-native/issues/2088). The basic desire is to have a declarative mechanism to transform text content to uppercase or lowercase or titlecase ("capitalized"). My test plan involves having added a test-case to the RNTester app within the `<Text>` component area. I then manually verified that the rendered content met my expectation. Here is the markup that exercises my enhancement: ``` <View> <Text style={{ textTransform: 'uppercase'}}> This text should be uppercased. </Text> <Text style={{ textTransform: 'lowercase'}}> This TEXT SHOULD be lowercased. </Text> <Text style={{ textTransform: 'capitalize'}}> This text should be CAPITALIZED. </Text> <Text style={{ textTransform: 'capitalize'}}> Mixed:{' '} <Text style={{ textTransform: 'uppercase'}}> uppercase{' '} </Text> <Text style={{ textTransform: 'lowercase'}}> LoWeRcAsE{' '} </Text> <Text style={{ textTransform: 'capitalize'}}> capitalize each word </Text> </Text> </View> ``` And here is a screenshot of the result: ![screen shot 2018-03-14 at 3 01 02 pm](https://user-images.githubusercontent.com/575821/37433772-7abe7fa0-279a-11e8-9ec9-fb3aa1952dad.png) [Website Documentation PR](https://github.com/facebook/react-native-website/pull/254) https://github.com/facebook/react-native-website/pull/254 [IOS] [ENHANCEMENT] [Text] - added textTransform style property enabling declarative casing transformations Closes https://github.com/facebook/react-native/pull/18387 Differential Revision: D7583315 Pulled By: shergin fbshipit-source-id: a5d22aea2aa4f494b7b25a055abe64799ccbaa79
2018-04-16 18:59:26 +03:00
RCTTextAttributesCompareOthers(_layoutDirection) &&
RCTTextAttributesCompareOthers(_textTransform);
}
@end