Skip to content

Instantly share code, notes, and snippets.

@dnfield
Created March 29, 2018 03:51
Show Gist options
  • Save dnfield/cb6fc61032074074662f07e466651706 to your computer and use it in GitHub Desktop.
Save dnfield/cb6fc61032074074662f07e466651706 to your computer and use it in GitHub Desktop.
parseSvgPath vs precompiled
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'PathTest',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
typedef void CanvasOp(Canvas c);
const List<String> pathStrs = const [
" M 210 130 C 145 130 110 80 110 80 S 75 25 10 25 m 0 105 c 65 0 100 -50 100 -50 s 35 -55 100 -55 ",
" M 240 90 c 0 30 7 50 50 0 c 43 -50 50 -30 50 0 c 0 83 -68 -34 -90 -30 C 240 60 240 90 240 90 z ",
"M80 170 C100 170 160 170 180 170Z",
"M5 260 C40 260 60 175 55 160 c -5 15 15 100 50 100Z",
"m 200 260 c 50 -40 50 -100 25 -100 s -25 60 25 100 ",
" M 360 100 C 420 90 460 140 450 190",
"M360 210 c 0 20 -16 36 -36 36 s -36 -16 -36 -36 s 16 -36 36 -36 s 36 16 36 36 z ",
"m 360 325 c -40 -60 95 -100 80 0 z ",
"M 15 20 Q 30 120 130 30 M 180 80 q -75 -100 -163 -60z",
"M372 130Q272 50 422 10zm70 0q50-150-80-90z",
"M224 103Q234 -12 304 33Z",
"M208 168Q258 268 308 168T258 118Q128 88 208 168z",
" M 60 100 Q -40 150 60 200 Q 160 150 60 100 z ",
"M240 296q25-100 47 0t47 0t47 0t47 0t47 0z",
"M172 193q-100 50 0 50Q72 243 172 293q100 -50 0 -50Q272 243 172 193z",
" M 62.00000 56.00000 L 113.96152 146.00000 L 10.03848 146.00000 L 62.00000 56.00000 Z M 62.00000 71.00000 L 100.97114 138.50000 L 23.02886 138.50000 L 62.00000 71.00000 Z ",
" M 177.00000 56.00000 L 228.96152 146.00000 L 125.03848 146.00000 L 177.00000 56.00000 Z M 177.00000 71.00000 L 215.97114 138.50000 L 138.02886 138.50000 L 177.00000 71.00000 Z ",
" M 240.00000 56.00000 H 270.00000 V 86.00000 H 300.00000 V 116.00000 H 330.00000 V 146.00000 H 240.00000 V 56.00000 Z ",
" M 350.00000 56.00000 H 380.00000 V 86.00000 H 410.00000 V 116.00000 H 440.00000 V 146.00000 H 350.00000 V 56.00000 Z ",
" M 62.00000 56.00000 113.96152 146.00000 10.03848 146.00000 62.00000 56.00000 Z M 62.00000 71.00000 100.97114 138.50000 23.02886 138.50000 62.00000 71.00000 Z ",
" M 177.00000 56.00000 228.96152 146.00000 125.03848 146.00000 177.00000 56.00000 Z M 177.00000 71.00000 215.97114 138.50000 138.02886 138.50000 177.00000 71.00000 Z ",
"M 100 100 C 100 20 200 20 200 100 S 300 180 300 100",
"M 100 250 S 200 200 200 250 300 300 300 250",
"M60,0 l60,0 l60,60 l0,60 l-60,60 l-60,0 l-60,-60 l0,-60 z",
"M 20 20 Q 50 10 80 20 110 30 140 20 170 10 200 20",
"M 20 50 T 50 50 80 50",
];
class _MyHomePageState extends State<MyHomePage> {
List<CanvasOp> ops = [];
List<CanvasOp> fromSvg = pathStrs
.map((pathStr) => (Canvas canvas) => canvas.drawPath(
Path.parseSvgPathData(pathStr), new Paint()..color = Colors.black87))
.toList();
List<CanvasOp> paths = [
(canvas) => canvas.drawPath(
new Path()
..moveTo(10.0, 10.0)
..lineTo(10.0, 90.0)
..lineTo(10.0, 90.0)
..lineTo(90.0, 10.0)
..lineTo(10.0, 10.0),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(10.0, 10.0)
..lineTo(90.0, 10.0)
..lineTo(90.0, 90.0)
..lineTo(10.0, 90.0)
..lineTo(10.0, 10.0),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(10.0, 10.0)
..lineTo(90.0, 10.0)
..lineTo(90.0, 90.0)
..lineTo(10.0, 90.0)
..lineTo(10.0, 10.0),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(210.0, 130.0)
..cubicTo(145.0, 130.0, 110.0, 80.0, 110.0, 80.0)
..cubicTo(110.0, 80.0, 75.0, 25.0, 10.0, 25.0)
..relativeMoveTo(0.0, 105.0)
..relativeCubicTo(65.0, 0.0, 100.0, -50.0, 100.0, -50.0)
..relativeCubicTo(100.0, -50.0, 35.0, -55.0, 100.0, -55.0),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(240.0, 90.0)
..relativeCubicTo(0.0, 30.0, 7.0, 50.0, 50.0, 0.0)
..relativeCubicTo(43.0, -50.0, 50.0, -30.0, 50.0, 0.0)
..relativeCubicTo(0.0, 83.0, -68.0, -34.0, -90.0, -30.0)
..cubicTo(240.0, 60.0, 240.0, 90.0, 240.0, 90.0)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(80.0, 170.0)
..cubicTo(100.0, 170.0, 160.0, 170.0, 180.0, 170.0)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(5.0, 260.0)
..cubicTo(40.0, 260.0, 60.0, 175.0, 55.0, 160.0)
..relativeCubicTo(-5.0, 15.0, 15.0, 100.0, 50.0, 100.0)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..relativeMoveTo(200.0, 260.0)
..relativeCubicTo(50.0, -40.0, 50.0, -100.0, 25.0, -100.0)
..relativeCubicTo(25.0, -100.0, -25.0, 60.0, 25.0, 100.0),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(360.0, 100.0)
..cubicTo(420.0, 90.0, 460.0, 140.0, 450.0, 190.0),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(360.0, 210.0)
..relativeCubicTo(0.0, 20.0, -16.0, 36.0, -36.0, 36.0)
..relativeCubicTo(-36.0, 36.0, -36.0, -16.0, -36.0, -36.0)
..relativeCubicTo(-36.0, -36.0, 16.0, -36.0, 36.0, -36.0)
..relativeCubicTo(36.0, -36.0, 36.0, 16.0, 36.0, 36.0)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..relativeMoveTo(360.0, 325.0)
..relativeCubicTo(-40.0, -60.0, 95.0, -100.0, 80.0, 0.0)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(15.0, 20.0)
..quadraticBezierTo(30.0, 120.0, 130.0, 30.0)
..moveTo(180.0, 80.0)
..relativeQuadraticBezierTo(-75.0, -100.0, -163.0, -60.0)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(372.0, 130.0)
..quadraticBezierTo(272.0, 50.0, 422.0, 10.0)
..close()
..relativeMoveTo(70.0, 0.0)
..relativeQuadraticBezierTo(50.0, -150.0, -80.0, -90.0)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(224.0, 103.0)
..quadraticBezierTo(234.0, -12.0, 304.0, 33.0)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(208.0, 168.0)
..quadraticBezierTo(258.0, 268.0, 308.0, 168.0)
..quadraticBezierTo(308.0, 168.0, 258.0, 118.0)
..quadraticBezierTo(128.0, 88.0, 208.0, 168.0)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(60.0, 100.0)
..quadraticBezierTo(-40.0, 150.0, 60.0, 200.0)
..quadraticBezierTo(160.0, 150.0, 60.0, 100.0)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(240.0, 296.0)
..relativeQuadraticBezierTo(25.0, -100.0, 47.0, 0.0)
..quadraticBezierTo(47.0, 0.0, 47.0, 0.0)
..quadraticBezierTo(47.0, 0.0, 47.0, 0.0)
..quadraticBezierTo(47.0, 0.0, 47.0, 0.0)
..quadraticBezierTo(47.0, 0.0, 47.0, 0.0)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(172.0, 193.0)
..relativeQuadraticBezierTo(-100.0, 50.0, 0.0, 50.0)
..quadraticBezierTo(72.0, 243.0, 172.0, 293.0)
..relativeQuadraticBezierTo(100.0, -50.0, 0.0, -50.0)
..quadraticBezierTo(272.0, 243.0, 172.0, 193.0)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(62.00000, 56.00000)
..lineTo(113.96152, 146.00000)
..lineTo(10.03848, 146.00000)
..lineTo(62.00000, 56.00000)
..close()
..moveTo(62.00000, 71.00000)
..lineTo(100.97114, 138.50000)
..lineTo(23.02886, 138.50000)
..lineTo(62.00000, 71.00000)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(177.00000, 56.00000)
..lineTo(228.96152, 146.00000)
..lineTo(125.03848, 146.00000)
..lineTo(177.00000, 56.00000)
..close()
..moveTo(177.00000, 71.00000)
..lineTo(215.97114, 138.50000)
..lineTo(138.02886, 138.50000)
..lineTo(177.00000, 71.00000)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(240.00000, 56.00000)
..lineTo(56.00000, 270.00000)
..lineTo(56.00000, 86.00000)
..lineTo(86.00000, 300.00000)
..lineTo(86.00000, 116.00000)
..lineTo(116.00000, 330.00000)
..lineTo(116.00000, 146.00000)
..lineTo(146.00000, 240.00000)
..lineTo(146.00000, 56.00000)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(350.00000, 56.00000)
..lineTo(56.00000, 380.00000)
..lineTo(56.00000, 86.00000)
..lineTo(86.00000, 410.00000)
..lineTo(86.00000, 116.00000)
..lineTo(116.00000, 440.00000)
..lineTo(116.00000, 146.00000)
..lineTo(146.00000, 350.00000)
..lineTo(146.00000, 56.00000)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(62.00000, 56.00000)
..moveTo(113.96152, 146.00000)
..moveTo(10.03848, 146.00000)
..moveTo(62.00000, 56.00000)
..close()
..moveTo(62.00000, 71.00000)
..moveTo(100.97114, 138.50000)
..moveTo(23.02886, 138.50000)
..moveTo(62.00000, 71.00000)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(177.00000, 56.00000)
..moveTo(228.96152, 146.00000)
..moveTo(125.03848, 146.00000)
..moveTo(177.00000, 56.00000)
..close()
..moveTo(177.00000, 71.00000)
..moveTo(215.97114, 138.50000)
..moveTo(138.02886, 138.50000)
..moveTo(177.00000, 71.00000)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(100.0, 100.0)
..cubicTo(100.0, 20.0, 200.0, 20.0, 200.0, 100.0)
..cubicTo(200.0, 100.0, 300.0, 180.0, 300.0, 100.0),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(100.0, 250.0)
..cubicTo(100.0, 250.0, 200.0, 200.0, 200.0, 250.0)
..cubicTo(200.0, 250.0, 300.0, 300.0, 300.0, 250.0),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(60.0, 0.0)
..relativeLineTo(60.0, 0.0)
..relativeLineTo(60.0, 60.0)
..relativeLineTo(0.0, 60.0)
..relativeLineTo(-60.0, 60.0)
..relativeLineTo(-60.0, 0.0)
..relativeLineTo(-60.0, -60.0)
..relativeLineTo(0.0, -60.0)
..close(),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(20.0, 20.0)
..quadraticBezierTo(50.0, 10.0, 80.0, 20.0)
..quadraticBezierTo(110.0, 30.0, 140.0, 20.0)
..quadraticBezierTo(170.0, 10.0, 200.0, 20.0),
new Paint()..color = Colors.black),
(canvas) => canvas.drawPath(
new Path()
..moveTo(20.0, 50.0)
..quadraticBezierTo(20.0, 50.0, 50.0, 50.0)
..quadraticBezierTo(50.0, 50.0, 80.0, 50.0),
new Paint()..color = Colors.black),
];
void _fromSvg() {
setState(() => ops = fromSvg);
}
void _fromPaths() {
setState(() => ops = paths);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
children: [
new CustomPaint(
size: const Size(300.0, 300.0),
painter: new PathPainter(ops),
),
new FlatButton(
child: const Text('FROM SVG'),
onPressed: _fromSvg,
),
new FlatButton(
child: const Text('FROM PATHS'),
onPressed: _fromPaths,
),
],
),
),
);
}
}
class PathPainter extends CustomPainter {
final List<CanvasOp> ops;
PathPainter(this.ops);
@override
bool shouldRepaint(PathPainter old) => false;
@override
void paint(Canvas canvas, Size size) {
final sw = new Stopwatch();
sw.start();
for (int i = 0; i < 1000; i++) {
for (var op in ops) {
op(canvas);
}
}
sw.stop();
print('Micro: ${sw.elapsedMicroseconds} - milli: ${sw.elapsedMilliseconds}');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment