Skip to content

Commit 1c45a66

Browse files
radial gradient ios conversion code
1 parent 93e7e30 commit 1c45a66

File tree

8 files changed

+233
-62
lines changed

8 files changed

+233
-62
lines changed

packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundImage-test.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -926,12 +926,11 @@ describe('processBackgroundImage', () => {
926926
{color: processColor('blue'), position: 40},
927927
]);
928928
expect(result[0].position).toEqual({x: '50%', y: 50});
929-
expect(result[0].size).toEqual({type: 'keyword', value: 'closest-side'});
929+
expect(result[0].size).toEqual('closest-side');
930930
expect(result[0].shape).toEqual('circle');
931931
expect(result[0].type).toEqual('radialGradient');
932932

933933
expect(result[1].size).toEqual({
934-
type: 'dimensions',
935934
x: 100,
936935
y: 100,
937936
});

packages/react-native/Libraries/StyleSheet/processBackgroundImage.js

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,7 @@ type LinearGradientBackgroundImage = {
4040
// Radial Gradient
4141
const RADIAL_SHAPE_REGEX = /^(circle|ellipse)(?:\s|$)/i;
4242
const DEFAULT_RADIAL_SHAPE = 'ellipse';
43-
const DEFAULT_RADIAL_SIZE = {
44-
type: 'keyword',
45-
value: 'farthest-corner',
46-
};
43+
const DEFAULT_RADIAL_SIZE = 'farthest-corner';
4744
const DEFAULT_RADIAL_POSITION = {
4845
x: '50%',
4946
y: '50%',
@@ -54,12 +51,8 @@ type RadialExtent =
5451
| 'farthest-corner'
5552
| 'farthest-side';
5653
type RadialGradientSize =
54+
| RadialExtent
5755
| {
58-
type: 'keyword',
59-
value: RadialExtent,
60-
}
61-
| {
62-
type: 'dimensions',
6356
x: string | number,
6457
y: string | number,
6558
};
@@ -166,17 +159,13 @@ export default function processBackgroundImage(
166159
bgImage.size === 'farthest-side' ||
167160
bgImage.size === 'farthest-corner')
168161
) {
169-
size = {
170-
type: 'keyword',
171-
value: bgImage.size,
172-
};
162+
size = bgImage.size;
173163
} else if (
174164
typeof bgImage.size === 'object' &&
175165
bgImage.size.x != null &&
176166
bgImage.size.y != null
177167
) {
178168
size = {
179-
type: 'dimensions',
180169
x: bgImage.size.x,
181170
y: bgImage.size.y,
182171
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import <UIKit/UIKit.h>
9+
#import <react/renderer/components/view/ViewProps.h>
10+
11+
NS_ASSUME_NONNULL_BEGIN
12+
13+
@interface RCTRadialGradient : NSObject
14+
15+
+ (CALayer *)gradientLayerWithSize:(CGSize)size gradient:(const facebook::react::RadialGradient &)gradient;
16+
17+
@end
18+
19+
NS_ASSUME_NONNULL_END

packages/react-native/ReactCommon/react/renderer/components/view/conversions.h

Lines changed: 90 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,6 +1180,44 @@ inline void fromRawValue(
11801180
}
11811181

11821182
std::string type = (std::string)(typeIt->second);
1183+
std::vector<ColorStop> colorStops;
1184+
auto colorStopsIt = rawBackgroundImageMap.find("colorStops");
1185+
1186+
if (colorStopsIt != rawBackgroundImageMap.end() &&
1187+
colorStopsIt->second.hasType<std::vector<RawValue>>()) {
1188+
auto rawColorStops =
1189+
static_cast<std::vector<RawValue>>(colorStopsIt->second);
1190+
1191+
for (const auto& stop : rawColorStops) {
1192+
if (stop.hasType<std::unordered_map<std::string, RawValue>>()) {
1193+
auto stopMap =
1194+
static_cast<std::unordered_map<std::string, RawValue>>(stop);
1195+
auto positionIt = stopMap.find("position");
1196+
auto colorIt = stopMap.find("color");
1197+
1198+
if (positionIt != stopMap.end() && colorIt != stopMap.end()) {
1199+
ColorStop colorStop;
1200+
if (positionIt->second.hasValue()) {
1201+
auto valueUnit = toValueUnit(positionIt->second);
1202+
if (!valueUnit) {
1203+
result = {};
1204+
return;
1205+
}
1206+
colorStop.position = valueUnit;
1207+
}
1208+
if (colorIt->second.hasValue()) {
1209+
fromRawValue(
1210+
context.contextContainer,
1211+
context.surfaceId,
1212+
colorIt->second,
1213+
colorStop.color);
1214+
}
1215+
colorStops.push_back(colorStop);
1216+
}
1217+
}
1218+
}
1219+
}
1220+
11831221
if (type == "linearGradient") {
11841222
LinearGradient linearGradient;
11851223

@@ -1213,43 +1251,62 @@ inline void fromRawValue(
12131251
}
12141252
}
12151253

1216-
auto colorStopsIt = rawBackgroundImageMap.find("colorStops");
1217-
if (colorStopsIt != rawBackgroundImageMap.end() &&
1218-
colorStopsIt->second.hasType<std::vector<RawValue>>()) {
1219-
auto rawColorStops =
1220-
static_cast<std::vector<RawValue>>(colorStopsIt->second);
1221-
1222-
for (const auto& stop : rawColorStops) {
1223-
if (stop.hasType<std::unordered_map<std::string, RawValue>>()) {
1224-
auto stopMap =
1225-
static_cast<std::unordered_map<std::string, RawValue>>(stop);
1226-
auto positionIt = stopMap.find("position");
1227-
auto colorIt = stopMap.find("color");
1228-
1229-
if (positionIt != stopMap.end() && colorIt != stopMap.end()) {
1230-
ColorStop colorStop;
1231-
if (positionIt->second.hasValue()) {
1232-
auto valueUnit = toValueUnit(positionIt->second);
1233-
if (!valueUnit) {
1234-
result = {};
1235-
return;
1236-
}
1237-
colorStop.position = valueUnit;
1238-
}
1239-
if (colorIt->second.hasValue()) {
1240-
fromRawValue(
1241-
context.contextContainer,
1242-
context.surfaceId,
1243-
colorIt->second,
1244-
colorStop.color);
1245-
}
1246-
linearGradient.colorStops.push_back(colorStop);
1247-
}
1254+
if (colorStops.size() > 0) {
1255+
linearGradient.colorStops = colorStops;
1256+
}
1257+
1258+
backgroundImage.push_back(std::move(linearGradient));
1259+
} else if (type == "radialGradient") {
1260+
RadialGradient radialGradient;
1261+
auto shapeIt = rawBackgroundImageMap.find("shape");
1262+
if (shapeIt != rawBackgroundImageMap.end() && shapeIt->second.hasType<std::string>()) {
1263+
auto shape = (std::string)(shapeIt->second);
1264+
radialGradient.shape = shape == "circle" ? RadialGradientShape::Circle : RadialGradientShape::Ellipse;
1265+
}
1266+
1267+
auto sizeIt = rawBackgroundImageMap.find("size");
1268+
if (sizeIt != rawBackgroundImageMap.end()) {
1269+
if (sizeIt->second.hasType<std::string>()) {
1270+
auto sizeStr = (std::string)(sizeIt->second);
1271+
if (sizeStr == "closest-side") {
1272+
radialGradient.size.value = RadialGradientSize::SizeKeyword::ClosestSide;
1273+
} else if (sizeStr == "farthest-side") {
1274+
radialGradient.size.value = RadialGradientSize::SizeKeyword::FarthestSide;
1275+
} else if (sizeStr == "closest-corner") {
1276+
radialGradient.size.value = RadialGradientSize::SizeKeyword::ClosestCorner;
1277+
} else if (sizeStr == "farthest-corner") {
1278+
radialGradient.size.value = RadialGradientSize::SizeKeyword::FarthestCorner;
1279+
}
1280+
} else if (sizeIt->second.hasType<std::unordered_map<std::string, RawValue>>()) {
1281+
auto sizeMap = static_cast<std::unordered_map<std::string, RawValue>>(sizeIt->second);
1282+
auto xIt = sizeMap.find("x");
1283+
auto yIt = sizeMap.find("y");
1284+
if (xIt != sizeMap.end() && yIt != sizeMap.end()) {
1285+
RadialGradientSize sizeObj;
1286+
sizeObj.value = RadialGradientSize::Dimensions{toValueUnit(xIt->second), toValueUnit(yIt->second)};
1287+
radialGradient.size = sizeObj;
1288+
}
1289+
}
1290+
1291+
auto positionIt = rawBackgroundImageMap.find("position");
1292+
if (positionIt != rawBackgroundImageMap.end() && positionIt->second.hasType<std::unordered_map<std::string, RawValue>>()) {
1293+
auto positionMap = static_cast<std::unordered_map<std::string, RawValue>>(positionIt->second);
1294+
auto xIt = positionMap.find("x");
1295+
auto yIt = positionMap.find("y");
1296+
if (xIt != positionMap.end() && yIt != positionMap.end()) {
1297+
auto x = toValueUnit(xIt->second);
1298+
auto y = toValueUnit(yIt->second);
1299+
radialGradient.position.x = x;
1300+
radialGradient.position.y = y;
12481301
}
12491302
}
12501303
}
12511304

1252-
backgroundImage.push_back(std::move(linearGradient));
1305+
if (colorStops.size() > 0) {
1306+
radialGradient.colorStops = colorStops;
1307+
}
1308+
1309+
backgroundImage.push_back(std::move(radialGradient));
12531310
}
12541311
}
12551312

packages/react-native/ReactCommon/react/renderer/graphics/BackgroundImage.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99

1010
#include <react/renderer/graphics/ColorComponents.h>
1111
#include <react/renderer/graphics/LinearGradient.h>
12+
#include <react/renderer/graphics/RadialGradient.h>
1213
#include <vector>
1314

1415
namespace facebook::react {
1516

16-
using BackgroundImage = std::variant<LinearGradient>;
17+
using BackgroundImage = std::variant<LinearGradient, RadialGradient>;
1718

1819
}; // namespace facebook::react
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
#include <react/renderer/graphics/ValueUnit.h>
11+
#include <react/renderer/graphics/Float.h>
12+
13+
namespace facebook::react {
14+
15+
struct ColorStop {
16+
bool operator==(const ColorStop& other) const = default;
17+
SharedColor color;
18+
ValueUnit position;
19+
};
20+
21+
struct ProcessedColorStop {
22+
bool operator==(const ProcessedColorStop& other) const = default;
23+
SharedColor color;
24+
std::optional<Float> position;
25+
};
26+
27+
}; // namespace facebook::react

packages/react-native/ReactCommon/react/renderer/graphics/LinearGradient.h

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <react/renderer/graphics/Float.h>
1111
#include <react/renderer/graphics/ValueUnit.h>
12+
#include <react/renderer/graphics/ColorStop.h>
1213
#include <string>
1314
#include <variant>
1415
#include <vector>
@@ -33,18 +34,6 @@ struct GradientDirection {
3334
}
3435
};
3536

36-
struct ColorStop {
37-
bool operator==(const ColorStop& other) const = default;
38-
SharedColor color;
39-
ValueUnit position;
40-
};
41-
42-
struct ProcessedColorStop {
43-
bool operator==(const ProcessedColorStop& other) const = default;
44-
SharedColor color;
45-
std::optional<Float> position;
46-
};
47-
4837
struct LinearGradient {
4938
GradientDirection direction;
5039
std::vector<ColorStop> colorStops;
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
#include <react/renderer/graphics/Float.h>
11+
#include <react/renderer/graphics/ValueUnit.h>
12+
#include <react/renderer/graphics/ColorStop.h>
13+
#include <string>
14+
#include <variant>
15+
#include <vector>
16+
17+
namespace facebook::react {
18+
19+
enum class RadialGradientShape {
20+
Circle,
21+
Ellipse
22+
};
23+
24+
struct RadialGradientSize {
25+
enum class SizeKeyword {
26+
ClosestSide,
27+
FarthestSide,
28+
ClosestCorner,
29+
FarthestCorner
30+
};
31+
32+
struct Dimensions {
33+
ValueUnit x;
34+
ValueUnit y;
35+
36+
bool operator==(const Dimensions& other) const {
37+
return x == other.x && y == other.y;
38+
}
39+
bool operator!=(const Dimensions& other) const {
40+
return !(*this == other);
41+
}
42+
};
43+
44+
std::variant<SizeKeyword, Dimensions> value;
45+
46+
bool operator==(const RadialGradientSize& other) const {
47+
if (std::holds_alternative<SizeKeyword>(value) && std::holds_alternative<SizeKeyword>(other.value)) {
48+
return std::get<SizeKeyword>(value) == std::get<SizeKeyword>(other.value);
49+
} else if (std::holds_alternative<Dimensions>(value) && std::holds_alternative<Dimensions>(other.value)) {
50+
return std::get<Dimensions>(value) == std::get<Dimensions>(other.value);
51+
}
52+
return false;
53+
}
54+
55+
bool operator!=(const RadialGradientSize& other) const {
56+
return !(*this == other);
57+
}
58+
};
59+
60+
struct RadialGradientPosition {
61+
ValueUnit x;
62+
ValueUnit y;
63+
64+
bool operator==(const RadialGradientPosition& other) const {
65+
return x == other.x && y == other.y;
66+
}
67+
68+
bool operator!=(const RadialGradientPosition& other) const {
69+
return !(*this == other);
70+
}
71+
};
72+
73+
struct RadialGradient {
74+
RadialGradientShape shape;
75+
RadialGradientSize size;
76+
RadialGradientPosition position;
77+
std::vector<ColorStop> colorStops;
78+
79+
bool operator==(const RadialGradient& other) const {
80+
return shape == other.shape &&
81+
size == other.size &&
82+
position == other.position &&
83+
colorStops == other.colorStops;
84+
}
85+
bool operator!=(const RadialGradient& other) const {
86+
return !(*this == other);
87+
}
88+
};
89+
90+
}; // namespace facebook::react

0 commit comments

Comments
 (0)