Skip to content

Commit 919e8c2

Browse files
authored
Support for TwoPointConical gradients (flutter#5275)
1 parent cdd7e08 commit 919e8c2

File tree

3 files changed

+64
-4
lines changed

3 files changed

+64
-4
lines changed

lib/ui/painting.dart

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2296,25 +2296,44 @@ class Gradient extends Shader {
22962296
/// If `matrix4` is provided, the gradient fill will be transformed by the
22972297
/// specified 4x4 matrix relative to the local coordinate system. `matrix4` must
22982298
/// be a column-major matrix packed into a list of 16 values.
2299+
///
2300+
/// If `focal` is provided and not equal to `center` or `focalRadius` is
2301+
/// provided and not equal to 0.0, the generated shader will be a two point
2302+
/// conical radial gradient, with `focal` being the center of the focal
2303+
/// circle and `focalRadius` being the radius of that circle. If `focal` is
2304+
/// provided and not equal to `center`, at least one of the two offsets must
2305+
/// not be equal to [Offset.zero].
22992306
Gradient.radial(
23002307
Offset center,
23012308
double radius,
23022309
List<Color> colors, [
23032310
List<double> colorStops,
23042311
TileMode tileMode = TileMode.clamp,
2305-
Float64List matrix4
2312+
Float64List matrix4,
2313+
Offset focal,
2314+
double focalRadius
23062315
]) : assert(_offsetIsValid(center)),
23072316
assert(colors != null),
23082317
assert(tileMode != null),
23092318
assert(matrix4 == null || _matrix4IsValid(matrix4)),
23102319
super._() {
2320+
focal ??= center;
2321+
focalRadius ??= 0.0;
23112322
_validateColorStops(colors, colorStops);
23122323
final Int32List colorsBuffer = _encodeColorList(colors);
23132324
final Float32List colorStopsBuffer = colorStops == null ? null : new Float32List.fromList(colorStops);
2314-
_constructor();
2315-
_initRadial(center.dx, center.dy, radius, colorsBuffer, colorStopsBuffer, tileMode.index, matrix4);
2325+
2326+
if (center == focal && focalRadius != 0.0) {
2327+
_constructor();
2328+
_initRadial(center.dx, center.dy, radius, colorsBuffer, colorStopsBuffer, tileMode.index, matrix4);
2329+
} else {
2330+
assert(center != Offset.zero || focal != Offset.zero); // will result in nullptr in Skia side
2331+
_constructor();
2332+
_initConical(focal.dx, focal.dy, focalRadius, center.dx, center.dy, radius, colorsBuffer, colorStopsBuffer, tileMode.index, matrix4);
2333+
}
23162334
}
23172335
void _initRadial(double centerX, double centerY, double radius, Int32List colors, Float32List colorStops, int tileMode, Float64List matrix4) native 'Gradient_initRadial';
2336+
void _initConical(double startX, double startY, double startRadius, double endX, double endY, double endRadius, Int32List colors, Float32List colorStops, int tileMode, Float64List matrix4) native 'Gradient_initTwoPointConical';
23182337

23192338
/// Creates a sweep gradient centered at `center` that starts at `startAngle`
23202339
/// and ends at `endAngle`.

lib/ui/painting/gradient.cc

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ IMPLEMENT_WRAPPERTYPEINFO(ui, Gradient);
2525
#define FOR_EACH_BINDING(V) \
2626
V(Gradient, initLinear) \
2727
V(Gradient, initRadial) \
28-
V(Gradient, initSweep)
28+
V(Gradient, initSweep) \
29+
V(Gradient, initTwoPointConical)
2930

3031
FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
3132

@@ -109,6 +110,35 @@ void CanvasGradient::initSweep(double center_x,
109110
has_matrix ? &sk_matrix : nullptr)));
110111
}
111112

113+
void CanvasGradient::initTwoPointConical(double start_x,
114+
double start_y,
115+
double start_radius,
116+
double end_x,
117+
double end_y,
118+
double end_radius,
119+
const tonic::Int32List& colors,
120+
const tonic::Float32List& color_stops,
121+
SkShader::TileMode tile_mode,
122+
const tonic::Float64List& matrix4) {
123+
FXL_DCHECK(colors.num_elements() == color_stops.num_elements() ||
124+
color_stops.data() == nullptr);
125+
126+
static_assert(sizeof(SkColor) == sizeof(int32_t),
127+
"SkColor doesn't use int32_t.");
128+
129+
SkMatrix sk_matrix;
130+
bool has_matrix = matrix4.data() != nullptr;
131+
if (has_matrix) {
132+
sk_matrix = ToSkMatrix(matrix4);
133+
}
134+
135+
set_shader(UIDartState::CreateGPUObject(SkGradientShader::MakeTwoPointConical(
136+
SkPoint::Make(start_x, start_y), start_radius,
137+
SkPoint::Make(end_x, end_y), end_radius,
138+
reinterpret_cast<const SkColor*>(colors.data()), color_stops.data(),
139+
colors.num_elements(), tile_mode, 0, has_matrix ? &sk_matrix : nullptr)));
140+
}
141+
112142
CanvasGradient::CanvasGradient() = default;
113143

114144
CanvasGradient::~CanvasGradient() = default;

lib/ui/painting/gradient.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@ class CanvasGradient : public Shader {
5252
double end_angle,
5353
const tonic::Float64List& matrix4);
5454

55+
void initTwoPointConical(double start_x,
56+
double start_y,
57+
double start_radius,
58+
double end_x,
59+
double end_y,
60+
double end_radius,
61+
const tonic::Int32List& colors,
62+
const tonic::Float32List& color_stops,
63+
SkShader::TileMode tile_mode,
64+
const tonic::Float64List& matrix4);
65+
5566
static void RegisterNatives(tonic::DartLibraryNatives* natives);
5667

5768
private:

0 commit comments

Comments
 (0)