diff --git a/.gitignore b/.gitignore index 33aad97d..8dd4cc08 100644 --- a/.gitignore +++ b/.gitignore @@ -14,5 +14,7 @@ doc/api/ coverage/ .project +# golden failure diffs +test/failures # Flutter crash logs /flutter_*.log diff --git a/CHANGELOG.md b/CHANGELOG.md index 22799c0f..a33039e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # CHANGES +## 0.17.0 + +- Make ColorFiltering apply to whole layer instead of per paint operation. +- **BREAKING** Remove `colorFilter` parameter from `VectorDrawable.draw`. +- Fix color filtering for text. + ## 0.16.1 - Support `image` tags in `defs`. diff --git a/lib/src/vector_drawable.dart b/lib/src/vector_drawable.dart index e0a11dfb..423361ae 100644 --- a/lib/src/vector_drawable.dart +++ b/lib/src/vector_drawable.dart @@ -30,7 +30,7 @@ abstract class Drawable { /// the `parentPaint` to optionally override the child's paint. /// /// The `bounds` specify the area to draw in. - void draw(Canvas canvas, ColorFilter colorFilter, Rect bounds); + void draw(Canvas canvas, Rect bounds); } /// A [Drawable] that can have a [DrawableStyle] applied to it. @@ -283,7 +283,7 @@ class DrawablePaint { final double strokeWidth; /// Creates a [Paint] object from this [DrawablePaint]. - Paint toFlutterPaint([ColorFilter colorFilterOverride]) { + Paint toFlutterPaint() { final Paint paint = Paint(); // Null chekcs are needed here because the setters assert. @@ -293,8 +293,8 @@ class DrawablePaint { if (color != null) { paint.color = color; } - if (colorFilterOverride != null || colorFilter != null) { - paint.colorFilter = colorFilterOverride ?? colorFilter; + if (colorFilter != null) { + paint.colorFilter = colorFilter; } if (filterQuality != null) { paint.filterQuality = filterQuality; @@ -507,7 +507,7 @@ class DrawableText implements Drawable { (fill?.width ?? 0.0) + (stroke?.width ?? 0.0) > 0.0; @override - void draw(Canvas canvas, ColorFilter colorFilter, Rect bounds) { + void draw(Canvas canvas, Rect bounds) { if (!hasDrawableContent) { return; } @@ -893,7 +893,7 @@ class DrawableRoot implements DrawableParent { !viewport.viewBox.isEmpty; @override - void draw(Canvas canvas, ColorFilter colorFilter, Rect bounds) { + void draw(Canvas canvas, Rect bounds) { if (!hasDrawableContent) { return; } @@ -907,7 +907,7 @@ class DrawableRoot implements DrawableParent { canvas.translate(viewport.viewBoxOffset.dx, viewport.viewBoxOffset.dy); } for (Drawable child in children) { - child.draw(canvas, colorFilter, viewport.viewBoxRect); + child.draw(canvas, viewport.viewBoxRect); } if (transform != null) { @@ -934,7 +934,11 @@ class DrawableRoot implements DrawableParent { final PictureRecorder recorder = PictureRecorder(); final Canvas canvas = Canvas(recorder, viewport.viewBoxRect); - canvas.save(); + if (colorFilter != null) { + canvas.saveLayer(null, Paint()..colorFilter = colorFilter); + } else { + canvas.save(); + } if (size != null) { scaleCanvasToViewBox(canvas, size); } @@ -942,7 +946,7 @@ class DrawableRoot implements DrawableParent { clipCanvasToViewBox(canvas); } - draw(canvas, colorFilter, viewport.viewBoxRect); + draw(canvas, viewport.viewBoxRect); canvas.restore(); return recorder.endRecording(); } @@ -988,7 +992,7 @@ class DrawableGroup implements DrawableStyleable, DrawableParent { bool get hasDrawableContent => children != null && children.isNotEmpty; @override - void draw(Canvas canvas, ColorFilter colorFilter, Rect bounds) { + void draw(Canvas canvas, Rect bounds) { if (!hasDrawableContent) { return; } @@ -1018,12 +1022,12 @@ class DrawableGroup implements DrawableStyleable, DrawableParent { } for (Drawable child in children) { - child.draw(canvas, colorFilter, bounds); + child.draw(canvas, bounds); } if (style.mask != null) { canvas.saveLayer(null, _grayscaleDstInPaint); - style.mask.draw(canvas, colorFilter, bounds); + style.mask.draw(canvas, bounds); canvas.restore(); } if (needsSaveLayer) { @@ -1103,7 +1107,7 @@ class DrawableRasterImage implements DrawableStyleable { final DrawableStyle style; @override - void draw(Canvas canvas, ColorFilter colorFilter, Rect bounds) { + void draw(Canvas canvas, Rect bounds) { final Size imageSize = Size( image.width.toDouble(), image.height.toDouble(), @@ -1190,7 +1194,7 @@ class DrawableShape implements DrawableStyleable { bool get hasDrawableContent => bounds.width + bounds.height > 0; @override - void draw(Canvas canvas, ColorFilter colorFilter, Rect bounds) { + void draw(Canvas canvas, Rect bounds) { if (!hasDrawableContent || style == null) { return; } @@ -1210,7 +1214,7 @@ class DrawableShape implements DrawableStyleable { } if (style.fill?.style != null) { assert(style.fill.style == PaintingStyle.fill); - canvas.drawPath(path, style.fill.toFlutterPaint(colorFilter)); + canvas.drawPath(path, style.fill.toFlutterPaint()); } if (style.stroke?.style != null) { @@ -1223,15 +1227,15 @@ class DrawableShape implements DrawableStyleable { dashArray: style.dashArray, dashOffset: style.dashOffset, ), - style.stroke.toFlutterPaint(colorFilter)); + style.stroke.toFlutterPaint()); } else { - canvas.drawPath(path, style.stroke.toFlutterPaint(colorFilter)); + canvas.drawPath(path, style.stroke.toFlutterPaint()); } } if (style.mask != null) { canvas.saveLayer(null, _grayscaleDstInPaint); - style.mask.draw(canvas, colorFilter, bounds); + style.mask.draw(canvas, bounds); canvas.restore(); canvas.restore(); } diff --git a/lib/svg.dart b/lib/svg.dart index 0b72b74b..318aac3f 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -1,6 +1,6 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:io'; +import 'dart:io' show File; import 'dart:typed_data'; import 'dart:ui' show Picture; diff --git a/pubspec.yaml b/pubspec.yaml index 95b1d4fb..204357b5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. homepage: https://github.com/dnfield/flutter_svg -version: 0.16.1 +version: 0.17.0 dependencies: path_drawing: ^0.4.1 diff --git a/test/golden_widget/flutter_logo.string.color_filter.png b/test/golden_widget/flutter_logo.string.color_filter.png new file mode 100644 index 00000000..d80af097 Binary files /dev/null and b/test/golden_widget/flutter_logo.string.color_filter.png differ diff --git a/test/golden_widget/text_color_filter.png b/test/golden_widget/text_color_filter.png new file mode 100644 index 00000000..5fe54102 Binary files /dev/null and b/test/golden_widget/text_color_filter.png differ diff --git a/test/widget_svg_test.dart b/test/widget_svg_test.dart index 4e448a62..08276792 100644 --- a/test/widget_svg_test.dart +++ b/test/widget_svg_test.dart @@ -13,10 +13,7 @@ import 'package:mockito/mockito.dart'; Future _checkWidgetAndGolden(Key key, String filename) async { final Finder widgetFinder = find.byKey(key); expect(widgetFinder, findsOneWidget); - if (Platform.isLinux) { - await expectLater( - widgetFinder, matchesGoldenFile('golden_widget/$filename')); - } + await expectLater(widgetFinder, matchesGoldenFile('golden_widget/$filename')); } void main() { @@ -388,6 +385,57 @@ void main() { expect(find.byType(Semantics), findsNothing); }, semanticsEnabled: true); + + testWidgets('SvgPicture colorFilter - flutter logo', + (WidgetTester tester) async { + final GlobalKey key = GlobalKey(); + await tester.pumpWidget( + RepaintBoundary( + key: key, + child: SvgPicture.string( + svgStr, + width: 100.0, + height: 100.0, + color: const Color(0xFF990000), + ), + ), + ); + + await tester.pumpAndSettle(); + await _checkWidgetAndGolden(key, 'flutter_logo.string.color_filter.png'); + }); + + testWidgets('SvgPicture colorFilter with text', (WidgetTester tester) async { + const String svgData = + ''' + + + + + + 2 + + + 1 + + +'''; + final GlobalKey key = GlobalKey(); + await tester.pumpWidget( + RepaintBoundary( + key: key, + child: SvgPicture.string( + svgData, + width: 100.0, + height: 100.0, + color: const Color(0xFF990000), + ), + ), + ); + + await tester.pumpAndSettle(); + await _checkWidgetAndGolden(key, 'text_color_filter.png'); + }, skip: !isLinux); } class MockAssetBundle extends Mock implements AssetBundle {} diff --git a/tool/gen_golden.dart b/tool/gen_golden.dart index 3800e3ee..6514b813 100644 --- a/tool/gen_golden.dart +++ b/tool/gen_golden.dart @@ -27,7 +27,7 @@ Future getSvgPngBytes(String svgData) async { svgRoot.clipCanvasToViewBox(canvas); canvas.drawPaint(Paint()..color = const Color(0xFFFFFFFF)); - svgRoot.draw(canvas, null, svgRoot.viewport.viewBoxRect); + svgRoot.draw(canvas, svgRoot.viewport.viewBoxRect); final Picture pict = rec.endRecording();