cc @gaaclarke
Testing against the fixes in flutter/engine#53261 the main issue of the orientation of unidirectional blurs is fixed, but there is still an inconsistency in the size of the directional blurs as can be seen in this test case:
test case
import 'dart:math';
import 'dart:ui';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
double rotate = 45.0 * pi / 180.0;
Widget makeRow(double cornerSize, double blurSize) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
CustomPaint(
painter: _RRectPainter(
cornerSize: cornerSize,
blurSize: blurSize,
scale: 0.5,
rotate: rotate,
),
size: const Size(150, 150),
),
CustomPaint(
painter: _RRectPathPainter(
cornerSize: cornerSize,
blurSize: blurSize,
scale: 0.5,
rotate: rotate,
),
size: const Size(150, 150),
),
CustomPaint(
painter: _RRectPainter(
cornerSize: cornerSize,
blurSize: blurSize,
scale: 1.0,
rotate: rotate,
),
size: const Size(150, 150),
),
CustomPaint(
painter: _RRectPathPainter(
cornerSize: cornerSize,
blurSize: blurSize,
scale: 1.0,
rotate: rotate,
),
size: const Size(150, 150),
),
],
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
makeRow(10, 10),
makeRow(10, 30),
makeRow(10, 50),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('rotation'),
Slider(
value: rotate,
min: 0.0,
max: pi * 2.0,
onChanged: (value) {
setState(() {
rotate = value;
});
},
),
],
),
],
),
),
);
}
}
class _RRectPainter extends CustomPainter {
_RRectPainter({
required this.cornerSize,
required this.blurSize,
required this.scale,
required this.rotate,
});
final double cornerSize;
final double blurSize;
final double scale;
final double rotate;
@override
void paint(Canvas canvas, Size size) {
canvas.translate(size.width * 0.5, size.height * 0.5);
canvas.rotate(rotate);
canvas.translate(-size.width * 0.5, -size.height * 0.5);
canvas.scale(scale, scale);
double w = size.width / scale;
double h = size.height / scale;
double c = cornerSize / scale;
Rect rect = Rect.fromLTRB(0, 0, w, h);
RRect rrect = RRect.fromRectXY(rect, c, c);
Paint paint = Paint()
..imageFilter = ImageFilter.blur(sigmaX: blurSize, sigmaY: 0.0, tileMode: TileMode.decal)
// ..maskFilter = MaskFilter.blur(BlurStyle.normal, blurSize)
..color = Colors.blue;
canvas.drawRRect(rrect, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
class _RRectPathPainter extends CustomPainter {
_RRectPathPainter({
required this.cornerSize,
required this.blurSize,
required this.scale,
required this.rotate,
});
final double cornerSize;
final double blurSize;
final double scale;
final double rotate;
@override
void paint(Canvas canvas, Size size) {
canvas.translate(size.width * 0.5, size.height * 0.5);
canvas.rotate(rotate);
canvas.translate(-size.width * 0.5, -size.height * 0.5);
canvas.scale(scale, scale);
double w = size.width / scale;
double h = size.height / scale;
double c = cornerSize / scale;
Path path = Path();
path.addRect(Rect.fromLTRB(c, 0, w - c, h));
path.addRect(Rect.fromLTRB(0, c, w, h - c));
path.addOval(Rect.fromLTRB(0, 0, c * 2, c * 2));
path.addOval(Rect.fromLTRB(w - c * 2, 0, w, c * 2));
path.addOval(Rect.fromLTRB(0, h - c * 2, c * 2, h));
path.addOval(Rect.fromLTRB(w - c * 2, h - c * 2, w, h));
Paint paint = Paint()
..imageFilter = ImageFilter.blur(sigmaX: blurSize, sigmaY: 0.0, tileMode: TileMode.decal)
// ..maskFilter = MaskFilter.blur(BlurStyle.normal, blurSize)
..color = Colors.blue;
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
Skia output
Impeller output
animated comparison
4条答案
按热度按时间atmip9wb1#
在那个PR之前,模糊半径看起来是否有所不同?如果是这样,可能会有一个缺失的效果转换。据我回忆,黄金测试并不能很好地捕获效果转换的错误。
fcipmucu2#
我能够在主版本上复现报告的错误。
运行主版本的flutter doctor -v:
e5nszbig3#
在那个PR之前,模糊半径看起来是否有所不同?如果是这样,可能会有一个缺失的效果变换。据我回忆,黄金测试并不能很好地捕获效果变换的bug。
我之前没有特别关注模糊大小,我是在运行修复后的代码来查看新代码的性能表现有多接近。
kuhbmx9i4#
我想要确保flutter/engine#53261没有因为缺少效果变换而破坏任何东西。那个PR并没有影响模糊大小
截图
有PR的
没有PR的