Showing
5 changed files
with
113 additions
and
21 deletions
| @@ -27,43 +27,52 @@ class SvgImage extends Widget { | @@ -27,43 +27,52 @@ class SvgImage extends Widget { | ||
| 27 | factory SvgImage({ | 27 | factory SvgImage({ |
| 28 | @required String svg, | 28 | @required String svg, |
| 29 | BoxFit fit = BoxFit.contain, | 29 | BoxFit fit = BoxFit.contain, |
| 30 | + Alignment alignment = Alignment.center, | ||
| 30 | bool clip = true, | 31 | bool clip = true, |
| 31 | double width, | 32 | double width, |
| 32 | double height, | 33 | double height, |
| 33 | }) { | 34 | }) { |
| 34 | assert(clip != null); | 35 | assert(clip != null); |
| 36 | + assert(alignment != null); | ||
| 35 | 37 | ||
| 36 | final xml = XmlDocument.parse(svg); | 38 | final xml = XmlDocument.parse(svg); |
| 37 | final parser = SvgParser(xml: xml); | 39 | final parser = SvgParser(xml: xml); |
| 38 | 40 | ||
| 39 | - return SvgImage._fromPainter( | 41 | + return SvgImage._fromParser( |
| 40 | parser, | 42 | parser, |
| 41 | fit, | 43 | fit, |
| 44 | + alignment, | ||
| 42 | clip, | 45 | clip, |
| 43 | width, | 46 | width, |
| 44 | height, | 47 | height, |
| 45 | ); | 48 | ); |
| 46 | } | 49 | } |
| 47 | 50 | ||
| 48 | - SvgImage._fromPainter( | 51 | + SvgImage._fromParser( |
| 49 | this._svgParser, | 52 | this._svgParser, |
| 50 | this.fit, | 53 | this.fit, |
| 54 | + this.alignment, | ||
| 51 | this.clip, | 55 | this.clip, |
| 52 | this.width, | 56 | this.width, |
| 53 | this.height, | 57 | this.height, |
| 54 | ) : assert(_svgParser != null), | 58 | ) : assert(_svgParser != null), |
| 55 | - assert(fit != null); | 59 | + assert(fit != null), |
| 60 | + assert(alignment != null); | ||
| 56 | 61 | ||
| 57 | final SvgParser _svgParser; | 62 | final SvgParser _svgParser; |
| 58 | 63 | ||
| 59 | final BoxFit fit; | 64 | final BoxFit fit; |
| 60 | 65 | ||
| 66 | + final Alignment alignment; | ||
| 67 | + | ||
| 61 | final bool clip; | 68 | final bool clip; |
| 62 | 69 | ||
| 63 | final double width; | 70 | final double width; |
| 64 | 71 | ||
| 65 | final double height; | 72 | final double height; |
| 66 | 73 | ||
| 74 | + FittedSizes sizes; | ||
| 75 | + | ||
| 67 | @override | 76 | @override |
| 68 | void layout(Context context, BoxConstraints constraints, | 77 | void layout(Context context, BoxConstraints constraints, |
| 69 | {bool parentUsesSize = false}) { | 78 | {bool parentUsesSize = false}) { |
| @@ -78,10 +87,7 @@ class SvgImage extends Widget { | @@ -78,10 +87,7 @@ class SvgImage extends Widget { | ||
| 78 | ? constraints.maxHeight | 87 | ? constraints.maxHeight |
| 79 | : constraints.constrainHeight(_svgParser.viewBox.height); | 88 | : constraints.constrainHeight(_svgParser.viewBox.height); |
| 80 | 89 | ||
| 81 | - final sizes = applyBoxFit( | ||
| 82 | - fit, | ||
| 83 | - PdfPoint(_svgParser.viewBox.width, _svgParser.viewBox.height), | ||
| 84 | - PdfPoint(w, h)); | 90 | + sizes = applyBoxFit(fit, _svgParser.viewBox.size, PdfPoint(w, h)); |
| 85 | box = PdfRect.fromPoints(PdfPoint.zero, sizes.destination); | 91 | box = PdfRect.fromPoints(PdfPoint.zero, sizes.destination); |
| 86 | } | 92 | } |
| 87 | 93 | ||
| @@ -89,19 +95,20 @@ class SvgImage extends Widget { | @@ -89,19 +95,20 @@ class SvgImage extends Widget { | ||
| 89 | void paint(Context context) { | 95 | void paint(Context context) { |
| 90 | super.paint(context); | 96 | super.paint(context); |
| 91 | 97 | ||
| 92 | - final mat = Matrix4.identity(); | ||
| 93 | - mat.translate( | ||
| 94 | - box.x, | ||
| 95 | - box.y + box.height, | ||
| 96 | - ); | ||
| 97 | - mat.scale( | ||
| 98 | - box.width / _svgParser.viewBox.width, | ||
| 99 | - -box.height / _svgParser.viewBox.height, | ||
| 100 | - ); | ||
| 101 | - mat.translate( | ||
| 102 | - -_svgParser.viewBox.x, | ||
| 103 | - -_svgParser.viewBox.y, | ||
| 104 | - ); | 98 | + final _alignment = Alignment(alignment.x, -alignment.y); |
| 99 | + final sourceRect = _alignment.inscribe(sizes.source, _svgParser.viewBox); | ||
| 100 | + final sx = sizes.destination.x / sizes.source.x; | ||
| 101 | + final sy = sizes.destination.y / sizes.source.y; | ||
| 102 | + final dx = sourceRect.x * sx; | ||
| 103 | + final dy = sourceRect.y * sy; | ||
| 104 | + | ||
| 105 | + final mat = Matrix4.identity() | ||
| 106 | + ..translate( | ||
| 107 | + box.x - dx, | ||
| 108 | + box.y + dy + box.height, | ||
| 109 | + ) | ||
| 110 | + ..scale(sx, -sy); | ||
| 111 | + | ||
| 105 | context.canvas.saveContext(); | 112 | context.canvas.saveContext(); |
| 106 | if (clip) { | 113 | if (clip) { |
| 107 | context.canvas | 114 | context.canvas |
| @@ -4,7 +4,7 @@ description: A pdf producer for Dart. It can create pdf files for both web or fl | @@ -4,7 +4,7 @@ description: A pdf producer for Dart. It can create pdf files for both web or fl | ||
| 4 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/pdf | 4 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/pdf |
| 5 | repository: https://github.com/DavBfr/dart_pdf | 5 | repository: https://github.com/DavBfr/dart_pdf |
| 6 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues | 6 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues |
| 7 | -version: 2.0.0 | 7 | +version: 2.1.0 |
| 8 | 8 | ||
| 9 | environment: | 9 | environment: |
| 10 | sdk: ">=2.3.0 <3.0.0" | 10 | sdk: ">=2.3.0 <3.0.0" |
| @@ -110,6 +110,72 @@ void main() { | @@ -110,6 +110,72 @@ void main() { | ||
| 110 | ); | 110 | ); |
| 111 | }); | 111 | }); |
| 112 | 112 | ||
| 113 | + test('SVG Widgets BoxFit.cover and alignment', () { | ||
| 114 | + const svg = | ||
| 115 | + '<?xml version="1.0" encoding="utf-8"?><svg version="1.1" viewBox="10 20 200 200" xmlns="http://www.w3.org/2000/svg"><circle style="fill-opacity: 0.19; fill: rgb(0, 94, 255);" cx="110" cy="120" r="90"/><rect x="10" y="20" width="200" height="200" stroke="blue" fill="none"/><line style="stroke: black;" x1="110" y1="110" x2="110" y2="130"/><line style="stroke: black" x1="100" y1="120" x2="120" y2="120"/></svg>'; | ||
| 116 | + | ||
| 117 | + pdf.addPage( | ||
| 118 | + Page( | ||
| 119 | + build: (context) => Column( | ||
| 120 | + children: [ | ||
| 121 | + GridView( | ||
| 122 | + crossAxisCount: 3, | ||
| 123 | + mainAxisSpacing: 10, | ||
| 124 | + crossAxisSpacing: 10, | ||
| 125 | + childAspectRatio: 0.3, | ||
| 126 | + children: [ | ||
| 127 | + for (final align in <Alignment>[ | ||
| 128 | + Alignment.topLeft, | ||
| 129 | + Alignment.topCenter, | ||
| 130 | + Alignment.topRight, | ||
| 131 | + Alignment.centerLeft, | ||
| 132 | + Alignment.center, | ||
| 133 | + Alignment.centerRight, | ||
| 134 | + Alignment.bottomLeft, | ||
| 135 | + Alignment.bottomCenter, | ||
| 136 | + Alignment.bottomRight, | ||
| 137 | + ]) | ||
| 138 | + SvgImage( | ||
| 139 | + svg: svg, | ||
| 140 | + fit: BoxFit.cover, | ||
| 141 | + alignment: align, | ||
| 142 | + ), | ||
| 143 | + ], | ||
| 144 | + ), | ||
| 145 | + SizedBox(height: 10), | ||
| 146 | + SizedBox( | ||
| 147 | + width: 180, | ||
| 148 | + child: GridView( | ||
| 149 | + crossAxisCount: 3, | ||
| 150 | + mainAxisSpacing: 10, | ||
| 151 | + crossAxisSpacing: 10, | ||
| 152 | + childAspectRatio: 3.3, | ||
| 153 | + children: [ | ||
| 154 | + for (final align in <Alignment>[ | ||
| 155 | + Alignment.topLeft, | ||
| 156 | + Alignment.topCenter, | ||
| 157 | + Alignment.topRight, | ||
| 158 | + Alignment.centerLeft, | ||
| 159 | + Alignment.center, | ||
| 160 | + Alignment.centerRight, | ||
| 161 | + Alignment.bottomLeft, | ||
| 162 | + Alignment.bottomCenter, | ||
| 163 | + Alignment.bottomRight, | ||
| 164 | + ]) | ||
| 165 | + SvgImage( | ||
| 166 | + svg: svg, | ||
| 167 | + fit: BoxFit.cover, | ||
| 168 | + alignment: align, | ||
| 169 | + ), | ||
| 170 | + ], | ||
| 171 | + ), | ||
| 172 | + ), | ||
| 173 | + ], | ||
| 174 | + ), | ||
| 175 | + ), | ||
| 176 | + ); | ||
| 177 | + }); | ||
| 178 | + | ||
| 113 | tearDownAll(() async { | 179 | tearDownAll(() async { |
| 114 | final file = File('widgets-svg.pdf'); | 180 | final file = File('widgets-svg.pdf'); |
| 115 | await file.writeAsBytes(await pdf.save()); | 181 | await file.writeAsBytes(await pdf.save()); |
| @@ -16,9 +16,11 @@ | @@ -16,9 +16,11 @@ | ||
| 16 | 16 | ||
| 17 | import 'dart:typed_data'; | 17 | import 'dart:typed_data'; |
| 18 | 18 | ||
| 19 | +import 'package:flutter/widgets.dart'; | ||
| 19 | import 'package:flutter_test/flutter_test.dart'; | 20 | import 'package:flutter_test/flutter_test.dart'; |
| 20 | import 'package:mockito/mockito.dart'; | 21 | import 'package:mockito/mockito.dart'; |
| 21 | import 'package:pdf/pdf.dart'; | 22 | import 'package:pdf/pdf.dart'; |
| 23 | + | ||
| 22 | import 'package:plugin_platform_interface/plugin_platform_interface.dart'; | 24 | import 'package:plugin_platform_interface/plugin_platform_interface.dart'; |
| 23 | import 'package:printing/printing.dart'; | 25 | import 'package:printing/printing.dart'; |
| 24 | import 'package:printing/src/interface.dart'; | 26 | import 'package:printing/src/interface.dart'; |
| @@ -112,6 +114,19 @@ void main() { | @@ -112,6 +114,19 @@ void main() { | ||
| 112 | null, | 114 | null, |
| 113 | ); | 115 | ); |
| 114 | }); | 116 | }); |
| 117 | + | ||
| 118 | + test('test image', () async { | ||
| 119 | + final bytes = Uint8List.fromList([ | ||
| 120 | + 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 1, // | ||
| 121 | + 0, 0, 0, 1, 0, 1, 3, 0, 0, 0, 102, 188, 58, 37, 0, 0, 0, 3, 80, 76, 84, | ||
| 122 | + 69, 181, 208, 208, 99, 4, 22, 234, 0, 0, 0, 31, 73, 68, 65, 84, 104, | ||
| 123 | + 129, 237, 193, 1, 13, 0, 0, 0, 194, 160, 247, 79, 109, 14, 55, 160, 0, 0, | ||
| 124 | + 0, 0, 0, 0, 0, 0, 190, 13, 33, 0, 0, 1, 154, 96, 225, 213, 0, 0, 0, 0, 73, | ||
| 125 | + 69, 78, 68, 174, 66, 96, 130 | ||
| 126 | + ]); | ||
| 127 | + final imageProvider = Image.memory(bytes).image; | ||
| 128 | + expect(await flutterImageProvider(imageProvider), isNotNull); | ||
| 129 | + }); | ||
| 115 | } | 130 | } |
| 116 | 131 | ||
| 117 | class MockPrinting extends Mock | 132 | class MockPrinting extends Mock |
-
Please register or login to post a comment