-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Closed
flutter/engine
#49309Labels
engineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.
Description
Before the DisplayList and Impeller were added to Flutter, 3 methods would handle unordered rectangles as if they were sorted. An unordered rectangle is one with a negative width or height, or right < left or bottom < top. While those rectangles would be considered empty by their own isEmpty property, they would render as if they were re-ordered such that width and height were > 0 in drawRect, drawOval, and clipRect as seen in the test sample below.
The example renders 4 boxes:
- 5 calls using an ordered rect in the upper left
- 5 calls using a horizontally flipped rect in the upper right
- 5 calls using a vertically flipped rect in the lower left
- 5 calls using a completely flipped (both horizontally and vertically) rect in the lower right
Each box contains 5 rendering calls within it:
- drawRect(filled) in the upper left
- drawOval(filled) in the upper right
- clipRect in the center
- drawRect(stroked) in the lower left
- drawOval(stroked) in the lower right
Unordered rect example code
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: CustomPaint(
foregroundPainter: _MyPainter(),
size: const Size(450, 450),
),
),
);
}
}
class _MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
canvas.drawRect(
Rect.fromLTWH(0, 0, size.width, size.height),
Paint()..color = Colors.grey.shade300,
);
void draw(Rect rect, double x, double y, Color color) {
Paint paint = Paint()
..color = color
..strokeWidth = 5.0;
canvas.save();
canvas.translate(x, y);
paint.style = PaintingStyle.fill;
canvas.drawRect(rect, paint);
canvas.save();
canvas.translate(0, 100);
paint.style = PaintingStyle.stroke;
canvas.drawRect(rect, paint);
canvas.restore();
canvas.save();
canvas.translate(100, 0);
paint.style = PaintingStyle.fill;
canvas.drawOval(rect, paint);
canvas.restore();
canvas.save();
canvas.translate(100, 100);
paint.style = PaintingStyle.stroke;
canvas.drawOval(rect, paint);
canvas.restore();
canvas.save();
canvas.translate(50, 50);
canvas.clipRect(rect);
canvas.drawPaint(paint);
canvas.restore();
canvas.restore();
}
draw(const Rect.fromLTRB(10, 10, 40, 40), 50, 50, Colors.blue);
draw(const Rect.fromLTRB(40, 10, 10, 40), 250, 50, Colors.green);
draw(const Rect.fromLTRB(10, 40, 40, 10), 50, 250, Colors.purple);
draw(const Rect.fromLTRB(40, 40, 10, 10), 250, 250, Colors.orange);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
Output on Flutter commit a7d2de2 (just before adding DisplayList) (all primitives render)
Metadata
Metadata
Assignees
Labels
engineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.
Type
Projects
Status
✅ Done
