Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
d27f5390
Commit
d27f5390
authored
Feb 26, 2019
by
Sander Kersten
Committed by
Michael Goderbauer
Feb 26, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add lerping between Gradients with arbitrary number of colors and stops (#27435)
parent
70c8b63e
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
319 additions
and
33 deletions
+319
-33
gradient.dart
packages/flutter/lib/src/painting/gradient.dart
+65
-27
gradient_test.dart
packages/flutter/test/painting/gradient_test.dart
+254
-6
No files found.
packages/flutter/lib/src/painting/gradient.dart
View file @
d27f5390
...
...
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:collection'
;
import
'dart:math'
as
math
;
import
'dart:ui'
as
ui
show
Gradient
,
lerpDouble
;
...
...
@@ -16,22 +17,43 @@ class _ColorsAndStops {
final
List
<
double
>
stops
;
}
_ColorsAndStops
_interpolateColorsAndStops
(
List
<
Color
>
aColors
,
List
<
double
>
aStops
,
List
<
Color
>
bColors
,
List
<
double
>
bStops
,
double
t
)
{
assert
(
aColors
.
length
==
bColors
.
length
,
'Cannot interpolate between two gradients with a different number of colors.'
);
// TODO(ianh): remove limitation
assert
((
aStops
==
null
&&
aColors
.
length
==
2
)
||
(
aStops
!=
null
&&
aStops
.
length
==
aColors
.
length
));
assert
((
bStops
==
null
&&
bColors
.
length
==
2
)
||
(
bStops
!=
null
&&
bStops
.
length
==
bColors
.
length
));
final
List
<
Color
>
interpolatedColors
=
<
Color
>[];
for
(
int
i
=
0
;
i
<
aColors
.
length
;
i
+=
1
)
interpolatedColors
.
add
(
Color
.
lerp
(
aColors
[
i
],
bColors
[
i
],
t
));
List
<
double
>
interpolatedStops
;
if
(
aStops
!=
null
||
bStops
!=
null
)
{
aStops
??=
const
<
double
>[
0.0
,
1.0
];
bStops
??=
const
<
double
>[
0.0
,
1.0
];
assert
(
aStops
.
length
==
bStops
.
length
);
interpolatedStops
=
<
double
>[];
for
(
int
i
=
0
;
i
<
aStops
.
length
;
i
+=
1
)
interpolatedStops
.
add
(
ui
.
lerpDouble
(
aStops
[
i
],
bStops
[
i
],
t
).
clamp
(
0.0
,
1.0
));
}
/// Calculate the color at position [t] of the gradient defined by [colors] and [stops].
Color
_sample
(
List
<
Color
>
colors
,
List
<
double
>
stops
,
double
t
)
{
assert
(
colors
!=
null
);
assert
(
colors
.
isNotEmpty
);
assert
(
stops
!=
null
);
assert
(
stops
.
isNotEmpty
);
assert
(
t
!=
null
);
if
(
t
<=
stops
.
first
)
return
colors
.
first
;
if
(
t
>=
stops
.
last
)
return
colors
.
last
;
final
int
index
=
stops
.
lastIndexWhere
((
double
s
)
=>
s
<=
t
);
assert
(
index
!=
-
1
);
return
Color
.
lerp
(
colors
[
index
],
colors
[
index
+
1
],
(
t
-
stops
[
index
])
/
(
stops
[
index
+
1
]
-
stops
[
index
])
);
}
_ColorsAndStops
_interpolateColorsAndStops
(
List
<
Color
>
aColors
,
List
<
double
>
aStops
,
List
<
Color
>
bColors
,
List
<
double
>
bStops
,
double
t
,
)
{
assert
(
aColors
.
length
>=
2
);
assert
(
bColors
.
length
>=
2
);
assert
(
aStops
.
length
==
aColors
.
length
);
assert
(
bStops
.
length
==
bColors
.
length
);
final
SplayTreeSet
<
double
>
stops
=
SplayTreeSet
<
double
>()
..
addAll
(
aStops
)
..
addAll
(
bStops
);
final
List
<
double
>
interpolatedStops
=
stops
.
toList
(
growable:
false
);
final
List
<
Color
>
interpolatedColors
=
interpolatedStops
.
map
<
Color
>(
(
double
stop
)
=>
Color
.
lerp
(
_sample
(
aColors
,
aStops
,
stop
),
_sample
(
bColors
,
bStops
,
stop
),
t
)
).
toList
(
growable:
false
);
return
_ColorsAndStops
(
interpolatedColors
,
interpolatedStops
);
}
...
...
@@ -88,8 +110,6 @@ abstract class Gradient {
List
<
double
>
_impliedStops
()
{
if
(
stops
!=
null
)
return
stops
;
if
(
colors
.
length
==
2
)
return
null
;
assert
(
colors
.
length
>=
2
,
'colors list must have at least two colors'
);
final
double
separation
=
1.0
/
(
colors
.
length
-
1
);
return
List
<
double
>.
generate
(
...
...
@@ -335,14 +355,14 @@ class LinearGradient extends Gradient {
@override
Gradient
lerpFrom
(
Gradient
a
,
double
t
)
{
if
(
a
==
null
||
(
a
is
LinearGradient
&&
a
.
colors
.
length
==
colors
.
length
))
// TODO(ianh): remove limitation
if
(
a
==
null
||
(
a
is
LinearGradient
))
return
LinearGradient
.
lerp
(
a
,
this
,
t
);
return
super
.
lerpFrom
(
a
,
t
);
}
@override
Gradient
lerpTo
(
Gradient
b
,
double
t
)
{
if
(
b
==
null
||
(
b
is
LinearGradient
&&
b
.
colors
.
length
==
colors
.
length
))
// TODO(ianh): remove limitation
if
(
b
==
null
||
(
b
is
LinearGradient
))
return
LinearGradient
.
lerp
(
this
,
b
,
t
);
return
super
.
lerpTo
(
b
,
t
);
}
...
...
@@ -374,7 +394,13 @@ class LinearGradient extends Gradient {
return
b
.
scale
(
t
);
if
(
b
==
null
)
return
a
.
scale
(
1.0
-
t
);
final
_ColorsAndStops
interpolated
=
_interpolateColorsAndStops
(
a
.
colors
,
a
.
stops
,
b
.
colors
,
b
.
stops
,
t
);
final
_ColorsAndStops
interpolated
=
_interpolateColorsAndStops
(
a
.
colors
,
a
.
_impliedStops
(),
b
.
colors
,
b
.
_impliedStops
(),
t
,
);
return
LinearGradient
(
begin:
AlignmentGeometry
.
lerp
(
a
.
begin
,
b
.
begin
,
t
),
end:
AlignmentGeometry
.
lerp
(
a
.
end
,
b
.
end
,
t
),
...
...
@@ -604,14 +630,14 @@ class RadialGradient extends Gradient {
@override
Gradient
lerpFrom
(
Gradient
a
,
double
t
)
{
if
(
a
==
null
||
(
a
is
RadialGradient
&&
a
.
colors
.
length
==
colors
.
length
))
// TODO(ianh): remove limitation
if
(
a
==
null
||
(
a
is
RadialGradient
))
return
RadialGradient
.
lerp
(
a
,
this
,
t
);
return
super
.
lerpFrom
(
a
,
t
);
}
@override
Gradient
lerpTo
(
Gradient
b
,
double
t
)
{
if
(
b
==
null
||
(
b
is
RadialGradient
&&
b
.
colors
.
length
==
colors
.
length
))
// TODO(ianh): remove limitation
if
(
b
==
null
||
(
b
is
RadialGradient
))
return
RadialGradient
.
lerp
(
this
,
b
,
t
);
return
super
.
lerpTo
(
b
,
t
);
}
...
...
@@ -643,7 +669,13 @@ class RadialGradient extends Gradient {
return
b
.
scale
(
t
);
if
(
b
==
null
)
return
a
.
scale
(
1.0
-
t
);
final
_ColorsAndStops
interpolated
=
_interpolateColorsAndStops
(
a
.
colors
,
a
.
stops
,
b
.
colors
,
b
.
stops
,
t
);
final
_ColorsAndStops
interpolated
=
_interpolateColorsAndStops
(
a
.
colors
,
a
.
_impliedStops
(),
b
.
colors
,
b
.
_impliedStops
(),
t
,
);
return
RadialGradient
(
center:
AlignmentGeometry
.
lerp
(
a
.
center
,
b
.
center
,
t
),
radius:
math
.
max
(
0.0
,
ui
.
lerpDouble
(
a
.
radius
,
b
.
radius
,
t
)),
...
...
@@ -835,14 +867,14 @@ class SweepGradient extends Gradient {
@override
Gradient
lerpFrom
(
Gradient
a
,
double
t
)
{
if
(
a
==
null
||
(
a
is
SweepGradient
&&
a
.
colors
.
length
==
colors
.
length
))
// TODO(ianh): remove limitation
if
(
a
==
null
||
(
a
is
SweepGradient
))
return
SweepGradient
.
lerp
(
a
,
this
,
t
);
return
super
.
lerpFrom
(
a
,
t
);
}
@override
Gradient
lerpTo
(
Gradient
b
,
double
t
)
{
if
(
b
==
null
||
(
b
is
SweepGradient
&&
b
.
colors
.
length
==
colors
.
length
))
// TODO(ianh): remove limitation
if
(
b
==
null
||
(
b
is
SweepGradient
))
return
SweepGradient
.
lerp
(
this
,
b
,
t
);
return
super
.
lerpTo
(
b
,
t
);
}
...
...
@@ -873,7 +905,13 @@ class SweepGradient extends Gradient {
return
b
.
scale
(
t
);
if
(
b
==
null
)
return
a
.
scale
(
1.0
-
t
);
final
_ColorsAndStops
interpolated
=
_interpolateColorsAndStops
(
a
.
colors
,
a
.
stops
,
b
.
colors
,
b
.
stops
,
t
);
final
_ColorsAndStops
interpolated
=
_interpolateColorsAndStops
(
a
.
colors
,
a
.
_impliedStops
(),
b
.
colors
,
b
.
_impliedStops
(),
t
,
);
return
SweepGradient
(
center:
AlignmentGeometry
.
lerp
(
a
.
center
,
b
.
center
,
t
),
startAngle:
math
.
max
(
0.0
,
ui
.
lerpDouble
(
a
.
startAngle
,
b
.
startAngle
,
t
)),
...
...
packages/flutter/test/painting/gradient_test.dart
View file @
d27f5390
...
...
@@ -56,6 +56,7 @@ void main() {
Color
(
0x3B3B3B3B
),
Color
(
0x77777777
),
],
stops:
<
double
>[
0
,
1
],
));
});
...
...
@@ -91,11 +92,84 @@ void main() {
end:
Alignment
(-
1.0
,
0.0
),
colors:
<
Color
>[
Color
(
0x3B3B3B3B
),
Color
(
0x55555555
),
Color
(
0x77777777
),
],
stops:
<
double
>[
0.25
,
0.75
,
0.0
,
0.5
,
1.0
,
],
));
});
test
(
'LinearGradient lerp test with unequal number of colors'
,
()
{
const
LinearGradient
testGradient1
=
LinearGradient
(
colors:
<
Color
>[
Color
(
0x22222222
),
Color
(
0x66666666
),
],
);
const
LinearGradient
testGradient2
=
LinearGradient
(
colors:
<
Color
>[
Color
(
0x44444444
),
Color
(
0x66666666
),
Color
(
0x88888888
),
],
);
final
LinearGradient
actual
=
LinearGradient
.
lerp
(
testGradient1
,
testGradient2
,
0.5
);
expect
(
actual
,
const
LinearGradient
(
colors:
<
Color
>[
Color
(
0x33333333
),
Color
(
0x55555555
),
Color
(
0x77777777
),
],
stops:
<
double
>[
0.0
,
0.5
,
1.0
,
],
));
});
test
(
'LinearGradient lerp test with stops and unequal number of colors'
,
()
{
const
LinearGradient
testGradient1
=
LinearGradient
(
colors:
<
Color
>[
Color
(
0x33333333
),
Color
(
0x66666666
),
],
stops:
<
double
>[
0.0
,
0.5
,
],
);
const
LinearGradient
testGradient2
=
LinearGradient
(
colors:
<
Color
>[
Color
(
0x44444444
),
Color
(
0x48484848
),
Color
(
0x88888888
),
],
stops:
<
double
>[
0.5
,
0.7
,
1.0
,
],
);
final
LinearGradient
actual
=
LinearGradient
.
lerp
(
testGradient1
,
testGradient2
,
0.5
);
expect
(
actual
,
const
LinearGradient
(
colors:
<
Color
>[
Color
(
0x3B3B3B3B
),
Color
(
0x55555555
),
Color
(
0x57575757
),
Color
(
0x77777777
),
],
stops:
<
double
>[
0.0
,
0.5
,
0.7
,
1.0
,
],
));
});
...
...
@@ -221,6 +295,10 @@ void main() {
Color
(
0x3B3B3B3B
),
Color
(
0x77777777
),
],
stops:
<
double
>[
0.0
,
1.0
,
],
));
});
...
...
@@ -259,11 +337,84 @@ void main() {
radius:
15.0
,
colors:
<
Color
>[
Color
(
0x3B3B3B3B
),
Color
(
0x55555555
),
Color
(
0x77777777
),
],
stops:
<
double
>[
0.0
,
0.5
,
1.0
],
));
});
test
(
'RadialGradient lerp test with unequal number of colors'
,
()
{
const
RadialGradient
testGradient1
=
RadialGradient
(
colors:
<
Color
>[
Color
(
0x22222222
),
Color
(
0x66666666
),
],
);
const
RadialGradient
testGradient2
=
RadialGradient
(
colors:
<
Color
>[
Color
(
0x44444444
),
Color
(
0x66666666
),
Color
(
0x88888888
),
],
);
final
RadialGradient
actual
=
RadialGradient
.
lerp
(
testGradient1
,
testGradient2
,
0.5
);
expect
(
actual
,
const
RadialGradient
(
colors:
<
Color
>[
Color
(
0x33333333
),
Color
(
0x55555555
),
Color
(
0x77777777
),
],
stops:
<
double
>[
0.25
,
0.75
,
0.0
,
0.5
,
1.0
,
],
));
});
test
(
'RadialGradient lerp test with stops and unequal number of colors'
,
()
{
const
RadialGradient
testGradient1
=
RadialGradient
(
colors:
<
Color
>[
Color
(
0x33333333
),
Color
(
0x66666666
),
],
stops:
<
double
>[
0.0
,
0.5
,
],
);
const
RadialGradient
testGradient2
=
RadialGradient
(
colors:
<
Color
>[
Color
(
0x44444444
),
Color
(
0x48484848
),
Color
(
0x88888888
),
],
stops:
<
double
>[
0.5
,
0.7
,
1.0
,
],
);
final
RadialGradient
actual
=
RadialGradient
.
lerp
(
testGradient1
,
testGradient2
,
0.5
);
expect
(
actual
,
const
RadialGradient
(
colors:
<
Color
>[
Color
(
0x3B3B3B3B
),
Color
(
0x55555555
),
Color
(
0x57575757
),
Color
(
0x77777777
),
],
stops:
<
double
>[
0.0
,
0.5
,
0.7
,
1.0
,
],
));
});
...
...
@@ -308,6 +459,10 @@ void main() {
Color
(
0x3B3B3B3B
),
Color
(
0x77777777
),
],
stops:
<
double
>[
0.0
,
1.0
,
],
));
final
RadialGradient
actual2
=
RadialGradient
.
lerp
(
testGradient1
,
testGradient3
,
0.5
);
...
...
@@ -320,6 +475,10 @@ void main() {
Color
(
0x3B3B3B3B
),
Color
(
0x77777777
),
],
stops:
<
double
>[
0.0
,
1.0
,
],
));
});
...
...
@@ -352,6 +511,10 @@ void main() {
Color
(
0x3B3B3B3B
),
Color
(
0x77777777
),
],
stops:
<
double
>[
0.0
,
1.0
,
],
));
});
...
...
@@ -390,11 +553,84 @@ void main() {
endAngle:
math
.
pi
*
3
/
4
,
colors:
<
Color
>[
Color
(
0x3B3B3B3B
),
Color
(
0x55555555
),
Color
(
0x77777777
),
],
stops:
<
double
>[
0.0
,
0.5
,
1.0
,
],
));
});
test
(
'SweepGradient lerp test with unequal number of colors'
,
()
{
const
SweepGradient
testGradient1
=
SweepGradient
(
colors:
<
Color
>[
Color
(
0x22222222
),
Color
(
0x66666666
),
],
);
const
SweepGradient
testGradient2
=
SweepGradient
(
colors:
<
Color
>[
Color
(
0x44444444
),
Color
(
0x66666666
),
Color
(
0x88888888
),
],
);
final
SweepGradient
actual
=
SweepGradient
.
lerp
(
testGradient1
,
testGradient2
,
0.5
);
expect
(
actual
,
const
SweepGradient
(
colors:
<
Color
>[
Color
(
0x33333333
),
Color
(
0x55555555
),
Color
(
0x77777777
),
],
stops:
<
double
>[
0.0
,
0.5
,
1.0
,
],
));
});
test
(
'SweepGradient lerp test with stops and unequal number of colors'
,
()
{
const
SweepGradient
testGradient1
=
SweepGradient
(
colors:
<
Color
>[
Color
(
0x33333333
),
Color
(
0x66666666
),
],
stops:
<
double
>[
0.0
,
0.5
,
],
);
const
SweepGradient
testGradient2
=
SweepGradient
(
colors:
<
Color
>[
Color
(
0x44444444
),
Color
(
0x48484848
),
Color
(
0x88888888
),
],
stops:
<
double
>[
0.5
,
0.7
,
1.0
,
],
);
final
SweepGradient
actual
=
SweepGradient
.
lerp
(
testGradient1
,
testGradient2
,
0.5
);
expect
(
actual
,
const
SweepGradient
(
colors:
<
Color
>[
Color
(
0x3B3B3B3B
),
Color
(
0x55555555
),
Color
(
0x57575757
),
Color
(
0x77777777
),
],
stops:
<
double
>[
0.25
,
0.75
,
0.0
,
0.5
,
0.7
,
1.0
,
],
));
});
...
...
@@ -431,6 +667,10 @@ void main() {
Color
(
0x33333333
),
Color
(
0x66666666
),
],
stops:
<
double
>[
0.0
,
1.0
,
],
);
const
RadialGradient
testGradient2
=
RadialGradient
(
center:
Alignment
(
0.0
,
-
1.0
),
...
...
@@ -439,6 +679,10 @@ void main() {
Color
(
0x3B3B3B3B
),
Color
(
0x77777777
),
],
stops:
<
double
>[
0.0
,
1.0
,
],
);
const
RadialGradient
testGradient3
=
RadialGradient
(
center:
Alignment
.
topRight
,
...
...
@@ -447,6 +691,10 @@ void main() {
Color
(
0x44444444
),
Color
(
0x88888888
),
],
stops:
<
double
>[
0.0
,
1.0
,
],
);
expect
(
Gradient
.
lerp
(
testGradient1
,
testGradient3
,
0.0
),
testGradient1
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment