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;
}
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
isEmptyproperty, 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:
Each box contains 5 rendering calls within it:
Unordered rect example code
Output on Flutter commit a7d2de2 (just before adding DisplayList) (all primitives render)
Output on the current Flutter ToT (notice missing clipRect output in the center of the unsorted test areas)