-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Closed
flutter/engine
#51668Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work liste: impellerImpeller rendering backend issues and features requestsImpeller rendering backend issues and features requestsengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.found in release: 3.19Found to occur in 3.19Found to occur in 3.19found in release: 3.21Found to occur in 3.21Found to occur in 3.21has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-engineOwned by Engine teamOwned by Engine teamtriaged-engineTriaged by Engine teamTriaged by Engine team
Description
Steps to reproduce
When utilizing a GradientTransform to scale and translate a RadialGradient, dithering artifacts are observed with the Impeller rendering engine, an issue that is not present when using Skia.
Expected results
Non dithering artifacts on Impeller
Actual results
Dithering artifacts on Impeller
Code sample
Code sample
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: Container(
width: 300,
height: 100,
decoration: BoxDecoration(
gradient: EllipticalGradient(
colors: [
Color(0xFF01F6BB).withOpacity(0.15),
Color(0xFF01F6BB).withOpacity(0),
],
stops: const [0.0, 1.0],
ellipseRelativeCenter: const Offset(0.5, 1),
ellipseScale: const Scale(widthFactor: 0.9, heightFactor: 0.6),
backgroundColor: Color(0xFF1C2B3E),
),
),
),
);
}
}
class EllipticalGradient extends Gradient {
final Color backgroundColor;
/// This offset is relative to top left of the widget, [0,0] means top left and [1,1] bottom right.
///
/// The range is not limited to [0,1] for both x and y axis.
final Offset ellipseRelativeCenter;
final Scale ellipseScale;
const EllipticalGradient({
required super.colors,
required this.backgroundColor,
required this.ellipseRelativeCenter,
required this.ellipseScale,
super.stops,
});
@override
Shader createShader(Rect rect, {TextDirection? textDirection}) {
return RadialGradient(
center: Alignment(ellipseRelativeCenter.dx * 2 - 1, ellipseRelativeCenter.dy * 2 - 1),
colors: colors.map((color) => Color.alphaBlend(color, backgroundColor)).toList(),
radius: 1,
stops: stops,
transform: _EllipseTransform(
ellipseRelativeCenter: ellipseRelativeCenter,
ellipseScale: ellipseScale,
),
).createShader(rect, textDirection: textDirection);
}
@override
EllipticalGradient scale(double factor) {
return EllipticalGradient(
backgroundColor: backgroundColor,
colors: colors.map<Color>((Color color) => Color.lerp(null, color, factor)!).toList(),
ellipseRelativeCenter: ellipseRelativeCenter,
ellipseScale: ellipseScale,
);
}
}
class _EllipseTransform extends GradientTransform {
final Offset ellipseRelativeCenter;
final Scale ellipseScale;
const _EllipseTransform({
required this.ellipseRelativeCenter,
required this.ellipseScale,
});
@override
Matrix4? transform(Rect bounds, {TextDirection? textDirection}) {
final double widthFactor;
final double heightFactor;
if (bounds.width > bounds.height) {
heightFactor = ellipseScale.heightFactor;
widthFactor = ellipseScale.widthFactor * bounds.width / bounds.height;
} else {
heightFactor = ellipseScale.heightFactor * bounds.height / bounds.width;
widthFactor = ellipseScale.widthFactor;
}
final transformMatrix = Matrix4.identity()..scale(widthFactor, heightFactor);
final Offset originalCenterOffset = Offset(
bounds.left + bounds.width * ellipseRelativeCenter.dx,
bounds.top + bounds.height * ellipseRelativeCenter.dy,
);
final List<double> offsetLocation =
transformMatrix.applyToVector3Array([originalCenterOffset.dx, originalCenterOffset.dy, 0.0]);
final dx = originalCenterOffset.dx - offsetLocation[0];
final dy = originalCenterOffset.dy - offsetLocation[1];
return transformMatrix..translate(dx / widthFactor, dy / heightFactor);
}
}
@immutable
class Scale {
final double heightFactor;
final double widthFactor;
const Scale({
required this.heightFactor,
required this.widthFactor,
});
}Screenshots or Video
Screenshots / Video demonstration
[Upload media here]
Logs
Logs
[Paste your logs here]Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.19.0, on macOS 14.0 23A344 darwin-arm64, locale en-FR)
• Flutter version 3.19.0 on channel stable at /Users/t.guerin-ext/fvm/versions/3.19.0
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision bae5e49bc2 (5 weeks ago), 2024-02-13 17:46:18 -0800
• Engine revision 04817c99c9
• Dart version 3.3.0
• DevTools version 2.31.1
[!] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
• Android SDK at /Users/t.guerin-ext/Library/Android/sdk
✗ cmdline-tools component is missing
Run `path/to/sdkmanager --install "cmdline-tools;latest"`
See https://developer.android.com/studio/command-line for more details.
✗ Android license status unknown.
Run `flutter doctor --android-licenses` to accept the SDK licenses.
See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✓] Xcode - develop for iOS and macOS (Xcode 15.3)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 15E204a
• CocoaPods version 1.13.0
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2023.2)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 17.0.9+0-17.0.9b1087.7-11185874)
[✓] IntelliJ IDEA Ultimate Edition (version 2023.3.5)
• IntelliJ at /Users/t.guerin-ext/Applications/IntelliJ IDEA Ultimate.app
• Flutter plugin version 78.1.1
• Dart plugin version 233.13763.5
[✓] Connected device (3 available)
• iPhone 15 (mobile) • E120F861-78FD-4111-A954-4EB49AC9A2C9 • ios • com.apple.CoreSimulator.SimRuntime.iOS-17-4 (simulator)
• macOS (desktop) • macos • darwin-arm64 • macOS 14.0 23A344 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 122.0.6261.129
[✓] Network resources
• All expected network resources are available.paulanatoleclaudot-betclic, lkervran, Youssef-Jdidi and 9AZX
Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work liste: impellerImpeller rendering backend issues and features requestsImpeller rendering backend issues and features requestsengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.found in release: 3.19Found to occur in 3.19Found to occur in 3.19found in release: 3.21Found to occur in 3.21Found to occur in 3.21has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-engineOwned by Engine teamOwned by Engine teamtriaged-engineTriaged by Engine teamTriaged by Engine team