mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
This was reverted because it failed to run. Colors were getting clamped in the dithering fragment shader. One change was made when relanding, i increased the epsilon for the radial and conical gradients. They don't appear to give back the exact color you asked for. Do not land until https://github.com/flutter/engine/pull/56140 is rolled into the framework. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
parent
9327c24d80
commit
5a11904383
@ -44,7 +44,8 @@ bool _isAlmost(double x, double y, double epsilon) {
|
|||||||
List<double> _deepRed = <double>[1.0931, -0.2268, -0.1501];
|
List<double> _deepRed = <double>[1.0931, -0.2268, -0.1501];
|
||||||
|
|
||||||
bool _findRGBAF16Color(
|
bool _findRGBAF16Color(
|
||||||
Uint8List bytes, int width, int height, List<double> color) {
|
Uint8List bytes, int width, int height, List<double> color,
|
||||||
|
{required double epsilon}) {
|
||||||
final ByteData byteData = ByteData.sublistView(bytes);
|
final ByteData byteData = ByteData.sublistView(bytes);
|
||||||
expect(bytes.lengthInBytes, width * height * 8);
|
expect(bytes.lengthInBytes, width * height * 8);
|
||||||
expect(bytes.lengthInBytes, byteData.lengthInBytes);
|
expect(bytes.lengthInBytes, byteData.lengthInBytes);
|
||||||
@ -54,9 +55,9 @@ bool _findRGBAF16Color(
|
|||||||
final double blue = _decodeHalf((pixel >> 32) & 0xffff);
|
final double blue = _decodeHalf((pixel >> 32) & 0xffff);
|
||||||
final double green = _decodeHalf((pixel >> 16) & 0xffff);
|
final double green = _decodeHalf((pixel >> 16) & 0xffff);
|
||||||
final double red = _decodeHalf((pixel >> 0) & 0xffff);
|
final double red = _decodeHalf((pixel >> 0) & 0xffff);
|
||||||
if (_isAlmost(red, color[0], 0.01) &&
|
if (_isAlmost(red, color[0], epsilon) &&
|
||||||
_isAlmost(green, color[1], 0.01) &&
|
_isAlmost(green, color[1], epsilon) &&
|
||||||
_isAlmost(blue, color[2], 0.01)) {
|
_isAlmost(blue, color[2], epsilon)) {
|
||||||
foundDeepRed = true;
|
foundDeepRed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,7 +65,8 @@ bool _findRGBAF16Color(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool _findBGRA10Color(
|
bool _findBGRA10Color(
|
||||||
Uint8List bytes, int width, int height, List<double> color) {
|
Uint8List bytes, int width, int height, List<double> color,
|
||||||
|
{required double epsilon}) {
|
||||||
final ByteData byteData = ByteData.sublistView(bytes);
|
final ByteData byteData = ByteData.sublistView(bytes);
|
||||||
expect(bytes.lengthInBytes, width * height * 8);
|
expect(bytes.lengthInBytes, width * height * 8);
|
||||||
expect(bytes.lengthInBytes, byteData.lengthInBytes);
|
expect(bytes.lengthInBytes, byteData.lengthInBytes);
|
||||||
@ -74,17 +76,17 @@ bool _findBGRA10Color(
|
|||||||
final double blue = _decodeBGR10((pixel >> 6) & 0x3ff);
|
final double blue = _decodeBGR10((pixel >> 6) & 0x3ff);
|
||||||
final double green = _decodeBGR10((pixel >> 22) & 0x3ff);
|
final double green = _decodeBGR10((pixel >> 22) & 0x3ff);
|
||||||
final double red = _decodeBGR10((pixel >> 38) & 0x3ff);
|
final double red = _decodeBGR10((pixel >> 38) & 0x3ff);
|
||||||
if (_isAlmost(red, color[0], 0.01) &&
|
if (_isAlmost(red, color[0], epsilon) &&
|
||||||
_isAlmost(green, color[1], 0.01) &&
|
_isAlmost(green, color[1], epsilon) &&
|
||||||
_isAlmost(blue, color[2], 0.01)) {
|
_isAlmost(blue, color[2], epsilon)) {
|
||||||
foundDeepRed = true;
|
foundDeepRed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return foundDeepRed;
|
return foundDeepRed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _findBGR10Color(
|
bool _findBGR10Color(Uint8List bytes, int width, int height, List<double> color,
|
||||||
Uint8List bytes, int width, int height, List<double> color) {
|
{required double epsilon}) {
|
||||||
final ByteData byteData = ByteData.sublistView(bytes);
|
final ByteData byteData = ByteData.sublistView(bytes);
|
||||||
expect(bytes.lengthInBytes, width * height * 4);
|
expect(bytes.lengthInBytes, width * height * 4);
|
||||||
expect(bytes.lengthInBytes, byteData.lengthInBytes);
|
expect(bytes.lengthInBytes, byteData.lengthInBytes);
|
||||||
@ -94,23 +96,27 @@ bool _findBGR10Color(
|
|||||||
final double blue = _decodeBGR10(pixel & 0x3ff);
|
final double blue = _decodeBGR10(pixel & 0x3ff);
|
||||||
final double green = _decodeBGR10((pixel >> 10) & 0x3ff);
|
final double green = _decodeBGR10((pixel >> 10) & 0x3ff);
|
||||||
final double red = _decodeBGR10((pixel >> 20) & 0x3ff);
|
final double red = _decodeBGR10((pixel >> 20) & 0x3ff);
|
||||||
if (_isAlmost(red, color[0], 0.01) &&
|
if (_isAlmost(red, color[0], epsilon) &&
|
||||||
_isAlmost(green, color[1], 0.01) &&
|
_isAlmost(green, color[1], epsilon) &&
|
||||||
_isAlmost(blue, color[2], 0.01)) {
|
_isAlmost(blue, color[2], epsilon)) {
|
||||||
foundDeepRed = true;
|
foundDeepRed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return foundDeepRed;
|
return foundDeepRed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _findColor(List<dynamic> result, List<double> color) {
|
bool _findColor(List<dynamic> result, List<double> color,
|
||||||
|
{double epsilon = 0.01}) {
|
||||||
expect(result, isNotNull);
|
expect(result, isNotNull);
|
||||||
expect(result.length, 4);
|
expect(result.length, 4);
|
||||||
final [int width, int height, String format, Uint8List bytes] = result;
|
final [int width, int height, String format, Uint8List bytes] = result;
|
||||||
return switch (format) {
|
return switch (format) {
|
||||||
'MTLPixelFormatBGR10_XR' => _findBGR10Color(bytes, width, height, color),
|
'MTLPixelFormatBGR10_XR' =>
|
||||||
'MTLPixelFormatBGRA10_XR' => _findBGRA10Color(bytes, width, height, color),
|
_findBGR10Color(bytes, width, height, color, epsilon: epsilon),
|
||||||
'MTLPixelFormatRGBA16Float' => _findRGBAF16Color(bytes, width, height, color),
|
'MTLPixelFormatBGRA10_XR' =>
|
||||||
|
_findBGRA10Color(bytes, width, height, color, epsilon: epsilon),
|
||||||
|
'MTLPixelFormatRGBA16Float' =>
|
||||||
|
_findRGBAF16Color(bytes, width, height, color, epsilon: epsilon),
|
||||||
_ => fail('Unsupported pixel format: $format'),
|
_ => fail('Unsupported pixel format: $format'),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -157,7 +163,8 @@ void main() {
|
|||||||
expect(_findColor(result, _deepRed), isTrue);
|
expect(_findColor(result, _deepRed), isTrue);
|
||||||
expect(_findColor(result, <double>[0.0, 1.0, 0.0]), isTrue);
|
expect(_findColor(result, <double>[0.0, 1.0, 0.0]), isTrue);
|
||||||
});
|
});
|
||||||
testWidgets('draw image with wide gamut works', (WidgetTester tester) async {
|
testWidgets('draw image with wide gamut works',
|
||||||
|
(WidgetTester tester) async {
|
||||||
app.run(app.Setup.drawnImage);
|
app.run(app.Setup.drawnImage);
|
||||||
await tester.pumpAndSettle(const Duration(seconds: 2));
|
await tester.pumpAndSettle(const Duration(seconds: 2));
|
||||||
|
|
||||||
@ -166,7 +173,8 @@ void main() {
|
|||||||
await channel.invokeMethod('test') as List<Object?>;
|
await channel.invokeMethod('test') as List<Object?>;
|
||||||
expect(_findColor(result, <double>[0.0, 1.0, 0.0]), isTrue);
|
expect(_findColor(result, <double>[0.0, 1.0, 0.0]), isTrue);
|
||||||
});
|
});
|
||||||
testWidgets('draw container with wide gamut works', (WidgetTester tester) async {
|
testWidgets('draw container with wide gamut works',
|
||||||
|
(WidgetTester tester) async {
|
||||||
app.run(app.Setup.container);
|
app.run(app.Setup.container);
|
||||||
await tester.pumpAndSettle(const Duration(seconds: 2));
|
await tester.pumpAndSettle(const Duration(seconds: 2));
|
||||||
|
|
||||||
@ -175,5 +183,49 @@ void main() {
|
|||||||
await channel.invokeMethod('test') as List<Object?>;
|
await channel.invokeMethod('test') as List<Object?>;
|
||||||
expect(_findColor(result, _deepRed), isTrue);
|
expect(_findColor(result, _deepRed), isTrue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('draw wide gamut linear gradient works',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
app.run(app.Setup.linearGradient);
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 2));
|
||||||
|
|
||||||
|
const MethodChannel channel = MethodChannel('flutter/screenshot');
|
||||||
|
final List<Object?> result =
|
||||||
|
await channel.invokeMethod('test') as List<Object?>;
|
||||||
|
expect(_findColor(result, _deepRed), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('draw wide gamut radial gradient works',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
app.run(app.Setup.radialGradient);
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 2));
|
||||||
|
|
||||||
|
const MethodChannel channel = MethodChannel('flutter/screenshot');
|
||||||
|
final List<Object?> result =
|
||||||
|
await channel.invokeMethod('test') as List<Object?>;
|
||||||
|
expect(_findColor(result, _deepRed, epsilon: 0.05), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('draw wide gamut conical gradient works',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
app.run(app.Setup.conicalGradient);
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 2));
|
||||||
|
|
||||||
|
const MethodChannel channel = MethodChannel('flutter/screenshot');
|
||||||
|
final List<Object?> result =
|
||||||
|
await channel.invokeMethod('test') as List<Object?>;
|
||||||
|
expect(_findColor(result, _deepRed, epsilon: 0.05), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('draw wide gamut sweep gradient works',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
app.run(app.Setup.sweepGradient);
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 2));
|
||||||
|
|
||||||
|
const MethodChannel channel = MethodChannel('flutter/screenshot');
|
||||||
|
final List<Object?> result =
|
||||||
|
await channel.invokeMethod('test') as List<Object?>;
|
||||||
|
expect(_findColor(result, _deepRed), isTrue);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ const String _displayP3Logo =
|
|||||||
'gr3yrjmlwqXLjmWw1O2I5Wmp9Xxjyh+AVIZ6ADIAqcwClakzeMgApDILVKbO4CED'
|
'gr3yrjmlwqXLjmWw1O2I5Wmp9Xxjyh+AVIZ6ADIAqcwClakzeMgApDILVKbO4CED'
|
||||||
'kMosUJk6g4dUBuRfvf1am9VRqzYAAAAASUVORK5CYII=';
|
'kMosUJk6g4dUBuRfvf1am9VRqzYAAAAASUVORK5CYII=';
|
||||||
|
|
||||||
void main() => run(Setup.container);
|
void main() => run(Setup.sweepGradient);
|
||||||
|
|
||||||
enum Setup {
|
enum Setup {
|
||||||
none,
|
none,
|
||||||
@ -146,6 +146,10 @@ enum Setup {
|
|||||||
blur,
|
blur,
|
||||||
drawnImage,
|
drawnImage,
|
||||||
container,
|
container,
|
||||||
|
linearGradient,
|
||||||
|
radialGradient,
|
||||||
|
conicalGradient,
|
||||||
|
sweepGradient,
|
||||||
}
|
}
|
||||||
|
|
||||||
void run(Setup setup) {
|
void run(Setup setup) {
|
||||||
@ -265,7 +269,14 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
_loadImage().then((ui.Image? value) => setState(() { _image = value; }));
|
_loadImage().then((ui.Image? value) => setState(() { _image = value; }));
|
||||||
case Setup.drawnImage:
|
case Setup.drawnImage:
|
||||||
_drawImage().then((ui.Image? value) => setState(() { _image = value; }));
|
_drawImage().then((ui.Image? value) => setState(() { _image = value; }));
|
||||||
case Setup.image || Setup.blur || Setup.none || Setup.container:
|
case Setup.image ||
|
||||||
|
Setup.blur ||
|
||||||
|
Setup.none ||
|
||||||
|
Setup.container ||
|
||||||
|
Setup.linearGradient ||
|
||||||
|
Setup.radialGradient ||
|
||||||
|
Setup.conicalGradient ||
|
||||||
|
Setup.sweepGradient:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -308,6 +319,97 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
green: 0,
|
green: 0,
|
||||||
blue: 0,
|
blue: 0,
|
||||||
colorSpace: ui.ColorSpace.displayP3));
|
colorSpace: ui.ColorSpace.displayP3));
|
||||||
|
case Setup.linearGradient:
|
||||||
|
imageWidget = Container(
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight,
|
||||||
|
colors: <Color>[
|
||||||
|
Color.from(
|
||||||
|
alpha: 1,
|
||||||
|
red: 1,
|
||||||
|
green: 0,
|
||||||
|
blue: 0,
|
||||||
|
colorSpace: ui.ColorSpace.displayP3),
|
||||||
|
Color.from(
|
||||||
|
alpha: 1,
|
||||||
|
red: 0,
|
||||||
|
green: 1,
|
||||||
|
blue: 0,
|
||||||
|
colorSpace: ui.ColorSpace.displayP3)],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
case Setup.radialGradient:
|
||||||
|
imageWidget = Container(
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
gradient: RadialGradient(
|
||||||
|
colors: <Color>[
|
||||||
|
Color.from(
|
||||||
|
alpha: 1,
|
||||||
|
red: 1,
|
||||||
|
green: 0,
|
||||||
|
blue: 0,
|
||||||
|
colorSpace: ui.ColorSpace.displayP3),
|
||||||
|
Color.from(
|
||||||
|
alpha: 1,
|
||||||
|
red: 0,
|
||||||
|
green: 1,
|
||||||
|
blue: 0,
|
||||||
|
colorSpace: ui.ColorSpace.displayP3)],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
case Setup.conicalGradient:
|
||||||
|
imageWidget = Container(
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
gradient: RadialGradient(
|
||||||
|
focal: Alignment(0.2, 0.2),
|
||||||
|
colors: <Color>[
|
||||||
|
Color.from(
|
||||||
|
alpha: 1,
|
||||||
|
red: 1,
|
||||||
|
green: 0,
|
||||||
|
blue: 0,
|
||||||
|
colorSpace: ui.ColorSpace.displayP3),
|
||||||
|
Color.from(
|
||||||
|
alpha: 1,
|
||||||
|
red: 0,
|
||||||
|
green: 1,
|
||||||
|
blue: 0,
|
||||||
|
colorSpace: ui.ColorSpace.displayP3)],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
case Setup.sweepGradient:
|
||||||
|
imageWidget = Container(
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
gradient: SweepGradient(
|
||||||
|
colors: <Color>[
|
||||||
|
Color.from(
|
||||||
|
alpha: 1,
|
||||||
|
red: 1,
|
||||||
|
green: 0,
|
||||||
|
blue: 0,
|
||||||
|
colorSpace: ui.ColorSpace.displayP3),
|
||||||
|
Color.from(
|
||||||
|
alpha: 1,
|
||||||
|
red: 0,
|
||||||
|
green: 1,
|
||||||
|
blue: 0,
|
||||||
|
colorSpace: ui.ColorSpace.displayP3)],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
Loading…
Reference in New Issue
Block a user