Skip to content

[iOS][backgroundImage] - Use CAGradientLayer for linear gradient #52096

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

intergalacticspacehighway
Copy link
Contributor

@intergalacticspacehighway intergalacticspacehighway commented Jun 18, 2025

Summary:

This PR replaces Core Graphics implementation with Core Animation for linear gradients. I came across a great solution that makes the CAGradientLayer's start and end point behaviour CSS spec compliant. This will make gradients much more performant.

Changelog:

[IOS] [CHANGED] - Optimised Linear Gradients.

Test Plan:

Non breaking change. Test Linear gradient example from RNTester. Compare results with web, android and iOS. Each platform should render the gradients identically.

Note:

I will be doing a PR to use CAGradientLayer for radial gradients as well. The next properties that I have locally working are background-size, background-position and background-repeat. These will be addressed in small PRs.

@facebook-github-bot facebook-github-bot added CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. labels Jun 18, 2025
@@ -16,6 +16,9 @@ NS_ASSUME_NONNULL_BEGIN
+ (std::vector<facebook::react::ProcessedColorStop>)getFixedColorStops:
(const std::vector<facebook::react::ColorStop> &)colorStops
gradientLineLength:(CGFloat)gradientLineLength;
+ (std::pair<CGPoint, CGPoint>)fixGradientPoints:(CGPoint)startPoint
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does fix mean here? Can you make the method name more meaningful or add a docblock?

if (std::isinf(slope)) {
return 0.0;
}
if (facebook::react::floatEquality(slope, 0.0f)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (facebook::react::floatEquality(slope, 0.0f)) {
if (floatEquality(slope, 0.0f)) {

CGFloat gradientLineLength = sqrt(dx * dx + dy * dy);
const auto colorStops = [RCTGradientUtils getFixedColorStops:gradient.colorStops
gradientLineLength:gradientLineLength];
NSMutableArray *colors = [NSMutableArray array];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add generic arg to type

Comment on lines 61 to 62
CGColorRef cgColor = RCTCreateCGColorRefFromSharedColor(colorStop.color);
[colors addObject:(__bridge id)cgColor];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use RCTUIColorFromSharedColor instead, so we don't need to call CGColorRelease

// CAGradientLayer linear gradient squishes the non-square gradient to square gradient.
// This function fixes the "squished" effect.
// See https://stackoverflow.com/a/43176174 for more information.
+ (std::pair<CGPoint, CGPoint>)fixGradientPoints:(CGPoint)startPoint
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a unit test for this method?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I should add one in the rn-tester/RNTesterUnitTests directory, correct?

CGFloat gradientLineLength = sqrt(dx * dx + dy * dy);
const auto colorStops = [RCTGradientUtils getFixedColorStops:gradient.colorStops
gradientLineLength:gradientLineLength];
NSMutableArray<id> *colors = [NSMutableArray array];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be NSMutableArray<UIColor *>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, actually the gradientLayer.colors require it to be CGColors 😕

@facebook-github-bot
Copy link
Contributor

@javache has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@facebook-github-bot
Copy link
Contributor

@javache has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@facebook-github-bot facebook-github-bot added the Merged This PR has been merged. label Jun 19, 2025
@facebook-github-bot
Copy link
Contributor

@javache merged this pull request in 2f3b104.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Merged This PR has been merged. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants