flutter/dev/benchmarks/macrobenchmarks/lib/src/very_long_picture_scrolling.dart
Michael Goderbauer 5491c8c146
Auto-format Framework (#160545)
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>
2024-12-19 20:06:21 +00:00

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;
}