Closed
Description
Consider an application that does a large amount of Canvas drawing. After flutter/engine#41606 , the computation of the Rtree can easily dwarf other costs in the raster thread, especially if the culling is unsuccessful.
We should be smarter about this, potentially by avoiding reaching into individual pictures and using those bounds as opposed to the individual ops.
Here is an application that will stress this code by drawing a large number of small objects. I was investigating this as a motivating case for a shape buffer to avoid circle tesellation.
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:math' as math;
import 'package:flutter/material.dart';
void main() {
runApp(const Example());
}
class Example extends StatefulWidget {
const Example({super.key});
@override
State<Example> createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
late Timer timer;
@override
void initState() {
super.initState();
timer = Timer.periodic(const Duration(milliseconds: 4), (t) {
setState(() {
});
});
}
@override
void dispose() {
timer.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(child:CustomPaint(painter: RandomCirclesPainter(
color: Colors.red,
radius: 0.5,
count: 5000
), size: const Size(400, 400),));
}
}
class RandomCirclesPainter extends CustomPainter {
RandomCirclesPainter({
required this.count,
required this.radius,
required this.color,
});
final int count;
final double radius;
final Color color;
@override
void paint(Canvas canvas, Size size) {
// Create a paint object with the specified color.
Paint paint = Paint()..color = color;
// Generate a random list of offsets for the circles.
List<Offset> offsets = List.generate(
count,
(_) => Offset(
math.Random().nextDouble() * size.width,
math.Random().nextDouble() * size.height,
),
);
// Draw the circles at the specified offsets.
for (Offset offset in offsets) {
canvas.drawCircle(
offset,
radius,
paint,
);
}
}
@override
bool shouldRepaint(RandomCirclesPainter oldDelegate) {
return true;
}
}