
This auto-formats all *.dart files in the repository outside of the `engine` subdirectory and enforces that these files stay formatted with a presubmit check. **Reviewers:** Please carefully review all the commits except for the one titled "formatted". The "formatted" commit was auto-generated by running `dev/tools/format.sh -a -f`. The other commits were hand-crafted to prepare the repo for the formatting change. I recommend reviewing the commits one-by-one via the "Commits" tab and avoiding Github's "Files changed" tab as it will likely slow down your browser because of the size of this PR. --------- Co-authored-by: Kate Lovett <katelovett@google.com> Co-authored-by: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com>
235 lines
7.1 KiB
Dart
235 lines
7.1 KiB
Dart
// 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:math';
|
|
import 'dart:typed_data';
|
|
import 'dart:ui';
|
|
import 'package:flutter/material.dart';
|
|
|
|
// Adapted from test case submitted in
|
|
// https://github.com/flutter/flutter/issues/92366
|
|
// Converted to use fixed data rather than reading a waveform file
|
|
class VeryLongPictureScrollingPerf extends StatefulWidget {
|
|
const VeryLongPictureScrollingPerf({super.key});
|
|
|
|
@override
|
|
State createState() => VeryLongPictureScrollingPerfState();
|
|
}
|
|
|
|
class VeryLongPictureScrollingPerfState extends State<VeryLongPictureScrollingPerf> {
|
|
bool consolidate = false;
|
|
bool useList = false;
|
|
Int16List waveData = loadGraph();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
actions: <Widget>[
|
|
Row(
|
|
children: <Widget>[
|
|
const Text('list:'),
|
|
Checkbox(
|
|
value: useList,
|
|
onChanged:
|
|
(bool? value) => setState(() {
|
|
useList = value!;
|
|
}),
|
|
),
|
|
],
|
|
),
|
|
Row(
|
|
children: <Widget>[
|
|
const Text('consolidate:'),
|
|
Checkbox(
|
|
value: consolidate,
|
|
onChanged:
|
|
(bool? value) => setState(() {
|
|
consolidate = value!;
|
|
}),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
backgroundColor: Colors.transparent,
|
|
body: SizedBox(
|
|
width: MediaQuery.of(context).size.width,
|
|
height: MediaQuery.of(context).size.height,
|
|
child:
|
|
useList
|
|
? ListView.builder(
|
|
key: const ValueKey<String>('vlp_list_view_scrollable'),
|
|
scrollDirection: Axis.horizontal,
|
|
clipBehavior: Clip.none,
|
|
itemCount: (waveData.length / 200).ceil(),
|
|
itemExtent: 100,
|
|
itemBuilder:
|
|
(BuildContext context, int index) => CustomPaint(
|
|
painter: PaintSomeTest(
|
|
waveData: waveData,
|
|
from: index * 200,
|
|
to: min((index + 1) * 200, waveData.length - 1),
|
|
),
|
|
),
|
|
)
|
|
: SingleChildScrollView(
|
|
key: const ValueKey<String>('vlp_single_child_scrollable'),
|
|
scrollDirection: Axis.horizontal,
|
|
child: SizedBox(
|
|
width: MediaQuery.of(context).size.width * 20,
|
|
height: MediaQuery.of(context).size.height,
|
|
child: RepaintBoundary(
|
|
child: CustomPaint(
|
|
isComplex: true,
|
|
painter: PaintTest(consolidate: consolidate, waveData: waveData),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class PaintTest extends CustomPainter {
|
|
const PaintTest({required this.consolidate, required this.waveData});
|
|
|
|
final bool consolidate;
|
|
final Int16List waveData;
|
|
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
final double halfHeight = size.height / 2;
|
|
double x = 0;
|
|
const double strokeSize = .5;
|
|
const double zoomFactor = .5;
|
|
|
|
final Paint paintPos =
|
|
Paint()
|
|
..color = Colors.pink
|
|
..strokeWidth = strokeSize
|
|
..isAntiAlias = false
|
|
..style = PaintingStyle.stroke;
|
|
|
|
final Paint paintNeg =
|
|
Paint()
|
|
..color = Colors.pink
|
|
..strokeWidth = strokeSize
|
|
..isAntiAlias = false
|
|
..style = PaintingStyle.stroke;
|
|
|
|
final Paint paintZero =
|
|
Paint()
|
|
..color = Colors.green
|
|
..strokeWidth = strokeSize
|
|
..isAntiAlias = false
|
|
..style = PaintingStyle.stroke;
|
|
|
|
int index = 0;
|
|
Paint? listPaint;
|
|
final Float32List offsets = Float32List(consolidate ? waveData.length * 4 : 4);
|
|
int used = 0;
|
|
for (index = 0; index < waveData.length; index++) {
|
|
final (Paint curPaint, Offset p1) = switch (waveData[index]) {
|
|
< 0 => (paintPos, Offset(x, halfHeight * (1 - waveData[index] / 32768))),
|
|
> 0 => (paintNeg, Offset(x, halfHeight * (1 - waveData[index] / 32767))),
|
|
_ => (paintZero, Offset(x, halfHeight + 1)),
|
|
};
|
|
final Offset p0 = Offset(x, halfHeight);
|
|
if (consolidate) {
|
|
if (listPaint != null && listPaint != curPaint) {
|
|
canvas.drawRawPoints(PointMode.lines, offsets.sublist(0, used), listPaint);
|
|
used = 0;
|
|
}
|
|
listPaint = curPaint;
|
|
offsets[used++] = p0.dx;
|
|
offsets[used++] = p0.dy;
|
|
offsets[used++] = p1.dx;
|
|
offsets[used++] = p1.dy;
|
|
} else {
|
|
canvas.drawLine(p0, p1, curPaint);
|
|
}
|
|
x += zoomFactor;
|
|
}
|
|
if (consolidate && used > 0) {
|
|
canvas.drawRawPoints(PointMode.lines, offsets.sublist(0, used), listPaint!);
|
|
}
|
|
}
|
|
|
|
@override
|
|
bool shouldRepaint(CustomPainter oldDelegate) {
|
|
return oldDelegate is! PaintTest ||
|
|
oldDelegate.consolidate != consolidate ||
|
|
oldDelegate.waveData != waveData;
|
|
}
|
|
}
|
|
|
|
class PaintSomeTest extends CustomPainter {
|
|
const PaintSomeTest({required this.waveData, int? from, int? to})
|
|
: from = from ?? 0,
|
|
to = to ?? waveData.length;
|
|
|
|
final Int16List waveData;
|
|
final int from;
|
|
final int to;
|
|
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
final double halfHeight = size.height / 2;
|
|
double x = 0;
|
|
const double strokeSize = .5;
|
|
const double zoomFactor = .5;
|
|
|
|
final Paint paintPos =
|
|
Paint()
|
|
..color = Colors.pink
|
|
..strokeWidth = strokeSize
|
|
..isAntiAlias = false
|
|
..style = PaintingStyle.stroke;
|
|
|
|
final Paint paintNeg =
|
|
Paint()
|
|
..color = Colors.pink
|
|
..strokeWidth = strokeSize
|
|
..isAntiAlias = false
|
|
..style = PaintingStyle.stroke;
|
|
|
|
final Paint paintZero =
|
|
Paint()
|
|
..color = Colors.green
|
|
..strokeWidth = strokeSize
|
|
..isAntiAlias = false
|
|
..style = PaintingStyle.stroke;
|
|
|
|
for (int index = from; index <= to; index++) {
|
|
final (Paint curPaint, Offset p1) = switch (waveData[index]) {
|
|
< 0 => (paintPos, Offset(x, halfHeight * (1 - waveData[index] / 32768))),
|
|
> 0 => (paintNeg, Offset(x, halfHeight * (1 - waveData[index] / 32767))),
|
|
_ => (paintZero, Offset(x, halfHeight + 1)),
|
|
};
|
|
final Offset p0 = Offset(x, halfHeight);
|
|
canvas.drawLine(p0, p1, curPaint);
|
|
x += zoomFactor;
|
|
}
|
|
}
|
|
|
|
@override
|
|
bool shouldRepaint(CustomPainter oldDelegate) {
|
|
return oldDelegate is! PaintSomeTest ||
|
|
oldDelegate.waveData != waveData ||
|
|
oldDelegate.from != from ||
|
|
oldDelegate.to != to;
|
|
}
|
|
}
|
|
|
|
Int16List loadGraph() {
|
|
final Int16List waveData = Int16List(350000);
|
|
final Random r = Random(0x42);
|
|
for (int i = 0; i < waveData.length; i++) {
|
|
waveData[i] = r.nextInt(32768) - 16384;
|
|
}
|
|
return waveData;
|
|
}
|