-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] Match Skia gradient clamping behavior (and document). #44825
Changes from all commits
e37122b
9a33cf4
2889fc0
1d06b5a
a2684bd
6efecf2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
#pragma once | ||
|
||
#include "display_list/dl_color.h" | ||
#include "display_list/effects/dl_color_source.h" | ||
#include "impeller/core/formats.h" | ||
#include "impeller/geometry/color.h" | ||
#include "impeller/geometry/path.h" | ||
|
@@ -47,5 +48,23 @@ Path PathDataFromTextBlob(const sk_sp<SkTextBlob>& blob, | |
|
||
std::optional<impeller::PixelFormat> ToPixelFormat(SkColorType type); | ||
|
||
/// @brief Convert display list colors + stops into impeller colors and stops, | ||
/// taking care to ensure that the stops monotonically increase from 0.0 to 1.0. | ||
/// | ||
/// The general process is: | ||
/// * Ensure that the first gradient stop value is 0.0. If not, insert a new | ||
/// stop with a value of 0.0 and use the first gradient color as this new | ||
/// stops color. | ||
/// * Ensure the last gradient stop value is 1.0. If not, insert a new stop | ||
/// with a value of 1.0 and use the last gradient color as this stops color. | ||
/// * Clamp all gradient values between the values of 0.0 and 1.0. | ||
/// * For all stop values, ensure that the values are monotonically increasing | ||
/// by clamping each value to a minimum of the previous stop value and itself. | ||
/// For example, with stop values of 0.0, 0.5, 0.4, 1.0, we would clamp such | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This bit is surprising to me. I would have expected it to be sorted but this works too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still WIP and confirming :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What did you end up finding out here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I found the w3c notes which basically confirm this behavior is approximately correct |
||
/// that the values were 0.0, 0.5, 0.5, 1.0. | ||
void ConvertStops(const flutter::DlGradientColorSourceBase* gradient, | ||
std::vector<Color>& colors, | ||
std::vector<float>& stops); | ||
|
||
} // namespace skia_conversions | ||
} // namespace impeller |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4191,7 +4191,11 @@ base class Gradient extends Shader { | |
/// If `colorStops` is provided, `colorStops[i]` is a number from 0.0 to 1.0 | ||
/// that specifies where `color[i]` begins in the gradient. If `colorStops` is | ||
/// not provided, then only two stops, at 0.0 and 1.0, are implied (and | ||
/// `color` must therefore only have two entries). | ||
/// `color` must therefore only have two entries). Stop values less than 0.0 | ||
/// will be rounded up to 0.0 and stop values greater than 1.0 will be rounded | ||
/// down to 1.0. Each stop value must be greater than or equal to the previous | ||
/// stop value. Stop values that do not meet this criteria will be rounded up | ||
/// to the previous stop value. | ||
/// | ||
/// The behavior before `from` and after `to` is described by the `tileMode` | ||
/// argument. For details, see the [TileMode] enum. | ||
|
@@ -4233,7 +4237,11 @@ base class Gradient extends Shader { | |
/// If `colorStops` is provided, `colorStops[i]` is a number from 0.0 to 1.0 | ||
/// that specifies where `color[i]` begins in the gradient. If `colorStops` is | ||
/// not provided, then only two stops, at 0.0 and 1.0, are implied (and | ||
/// `color` must therefore only have two entries). | ||
/// `color` must therefore only have two entries). Stop values less than 0.0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The docstring in the C++ header indicates that the second color is optional and the first will be repeated. Perhaps add that here too. Unless the framework has additional checks in place. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That isn't a valid gradient according to our docs, but w3c says this should degrade to a solid color fill. I'd rather punt on this behavior. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍🏽 |
||
/// will be rounded up to 0.0 and stop values greater than 1.0 will be rounded | ||
/// down to 1.0. Each stop value must be greater than or equal to the previous | ||
/// stop value. Stop values that do not meet this criteria will be rounded up | ||
/// to the previous stop value. | ||
/// | ||
/// The behavior before and after the radius is described by the `tileMode` | ||
/// argument. For details, see the [TileMode] enum. | ||
|
@@ -4295,7 +4303,11 @@ base class Gradient extends Shader { | |
/// If `colorStops` is provided, `colorStops[i]` is a number from 0.0 to 1.0 | ||
/// that specifies where `color[i]` begins in the gradient. If `colorStops` is | ||
/// not provided, then only two stops, at 0.0 and 1.0, are implied (and | ||
/// `color` must therefore only have two entries). | ||
/// `color` must therefore only have two entries). Stop values less than 0.0 | ||
/// will be rounded up to 0.0 and stop values greater than 1.0 will be rounded | ||
/// down to 1.0. Each stop value must be greater than or equal to the previous | ||
/// stop value. Stop values that do not meet this criteria will be rounded up | ||
/// to the previous stop value. | ||
/// | ||
/// The behavior before `startAngle` and after `endAngle` is described by the | ||
/// `tileMode` argument. For details, see the [TileMode] enum. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this approach generally and the docstring LGTM!
One question though, does that mean we could enforce (with DCHECKs?) deeper in the stack that stops/colors are valid?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not, because we've never enforced this so adding more enforcement is breaking.