Skip to content

Commit

Permalink
fix: flame svg perfomance
Browse files Browse the repository at this point in the history
  • Loading branch information
erickzanardo committed Feb 15, 2022
1 parent c753fc4 commit f422b67
Showing 1 changed file with 36 additions and 4 deletions.
40 changes: 36 additions & 4 deletions packages/flame_svg/lib/svg.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import 'dart:ui';

import 'package:flame/assets.dart';
import 'package:flame/cache.dart';
import 'package:flame/extensions.dart';
import 'package:flame/flame.dart';
import 'package:flame/game.dart';
Expand All @@ -12,6 +15,12 @@ class Svg {
/// Creates an [Svg] with the received [svgRoot].
Svg(this.svgRoot);

final MemoryCache<Vector2, Image> _imageCache = MemoryCache();

final _paint = Paint()..filterQuality = FilterQuality.high;

final List<Vector2> _lock = [];

/// Loads an [Svg] with the received [cache]. When no [cache] is provided,
/// the global [Flame.assets] is used.
static Future<Svg> load(String fileName, {AssetsCache? cache}) async {
Expand All @@ -22,10 +31,11 @@ class Svg {

/// Renders the svg on the [canvas] using the dimensions provided by [size].
void render(Canvas canvas, Vector2 size) {
canvas.save();
svgRoot.scaleCanvasToViewBox(canvas, size.toSize());
svgRoot.draw(canvas, svgRoot.viewport.viewBoxRect);
canvas.restore();
final image = _getImage(size);

if (image != null) {
canvas.drawImage(image, Offset.zero, _paint);
}
}

/// Renders the svg on the [canvas] on the given [position] using the
Expand All @@ -37,6 +47,28 @@ class Svg {
) {
canvas.renderAt(position, (c) => render(c, size));
}

Image? _getImage(Vector2 size) {
final image = _imageCache.getValue(size);

if (image == null && !_lock.contains(size)) {
_lock.add(size);
final recorder = PictureRecorder();

final canvas = Canvas(recorder);
svgRoot.scaleCanvasToViewBox(canvas, size.toSize());
svgRoot.draw(canvas, svgRoot.viewport.viewBoxRect);
final _picture = recorder.endRecording();

_picture.toImage(size.x.toInt(), size.y.toInt()).then((image) {
_imageCache.setValue(size, image);
_lock.remove(size);
_picture.dispose();
});
}

return image;
}
}

/// Provides a loading method for [Svg] on the [Game] class.
Expand Down

0 comments on commit f422b67

Please sign in to comment.