Showing
5 changed files
with
108 additions
and
11 deletions
| @@ -18,9 +18,73 @@ | @@ -18,9 +18,73 @@ | ||
| 18 | 18 | ||
| 19 | part of widget; | 19 | part of widget; |
| 20 | 20 | ||
| 21 | +void _paintImage({ | ||
| 22 | + @required PdfGraphics canvas, | ||
| 23 | + @required PdfRect rect, | ||
| 24 | + @required PdfImage image, | ||
| 25 | + double scale = 1.0, | ||
| 26 | + BoxFit fit, | ||
| 27 | + Alignment alignment = Alignment.center, | ||
| 28 | +}) { | ||
| 29 | + assert(canvas != null); | ||
| 30 | + assert(image != null); | ||
| 31 | + assert(alignment != null); | ||
| 32 | + final PdfPoint outputSize = rect.size; | ||
| 33 | + final PdfPoint inputSize = | ||
| 34 | + PdfPoint(image.width.toDouble(), image.height.toDouble()); | ||
| 35 | + fit ??= BoxFit.scaleDown; | ||
| 36 | + final FittedSizes fittedSizes = applyBoxFit( | ||
| 37 | + fit, PdfPoint(inputSize.x / scale, inputSize.y / scale), outputSize); | ||
| 38 | + final PdfPoint sourceSize = | ||
| 39 | + PdfPoint(fittedSizes.source.x * scale, fittedSizes.source.y * scale); | ||
| 40 | + final PdfPoint destinationSize = fittedSizes.destination; | ||
| 41 | + final double halfWidthDelta = (outputSize.x - destinationSize.x) / 2.0; | ||
| 42 | + final double halfHeightDelta = (outputSize.y - destinationSize.y) / 2.0; | ||
| 43 | + final double dx = halfWidthDelta + alignment.x * halfWidthDelta; | ||
| 44 | + final double dy = halfHeightDelta + alignment.y * halfHeightDelta; | ||
| 45 | + | ||
| 46 | + final PdfPoint destinationPosition = rect.topLeft.translate(dx, dy); | ||
| 47 | + final PdfRect destinationRect = | ||
| 48 | + PdfRect.fromPoints(destinationPosition, destinationSize); | ||
| 49 | + final PdfRect sourceRect = alignment.inscribe( | ||
| 50 | + sourceSize, | ||
| 51 | + PdfRect.fromPoints(PdfPoint.zero, inputSize), | ||
| 52 | + ); | ||
| 53 | + _drawImageRect(canvas, image, sourceRect, destinationRect); | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +void _drawImageRect(PdfGraphics canvas, PdfImage image, PdfRect sourceRect, | ||
| 57 | + PdfRect destinationRect) { | ||
| 58 | + final double fw = destinationRect.width / sourceRect.width; | ||
| 59 | + final double fh = destinationRect.height / sourceRect.height; | ||
| 60 | + | ||
| 61 | + canvas.saveContext(); | ||
| 62 | + canvas | ||
| 63 | + ..drawRect( | ||
| 64 | + destinationRect.x, | ||
| 65 | + destinationRect.y, | ||
| 66 | + destinationRect.width, | ||
| 67 | + destinationRect.height, | ||
| 68 | + ) | ||
| 69 | + ..clipPath() | ||
| 70 | + ..drawImage( | ||
| 71 | + image, | ||
| 72 | + destinationRect.x - sourceRect.x * fw, | ||
| 73 | + destinationRect.y - sourceRect.y * fh, | ||
| 74 | + image.width.toDouble() * fw, | ||
| 75 | + image.height.toDouble() * fh, | ||
| 76 | + ) | ||
| 77 | + ..restoreContext(); | ||
| 78 | +} | ||
| 79 | + | ||
| 21 | class Image extends Widget { | 80 | class Image extends Widget { |
| 22 | - Image(this.image, {this.fit = BoxFit.contain}) | ||
| 23 | - : assert(image != null), | 81 | + Image( |
| 82 | + this.image, { | ||
| 83 | + this.fit = BoxFit.contain, | ||
| 84 | + this.alignment = Alignment.center, | ||
| 85 | + this.width, | ||
| 86 | + this.height, | ||
| 87 | + }) : assert(image != null), | ||
| 24 | aspectRatio = image.height.toDouble() / image.width.toDouble(); | 88 | aspectRatio = image.height.toDouble() / image.width.toDouble(); |
| 25 | 89 | ||
| 26 | final PdfImage image; | 90 | final PdfImage image; |
| @@ -29,6 +93,12 @@ class Image extends Widget { | @@ -29,6 +93,12 @@ class Image extends Widget { | ||
| 29 | 93 | ||
| 30 | final BoxFit fit; | 94 | final BoxFit fit; |
| 31 | 95 | ||
| 96 | + final Alignment alignment; | ||
| 97 | + | ||
| 98 | + final double width; | ||
| 99 | + | ||
| 100 | + final double height; | ||
| 101 | + | ||
| 32 | @override | 102 | @override |
| 33 | void layout(Context context, BoxConstraints constraints, | 103 | void layout(Context context, BoxConstraints constraints, |
| 34 | {bool parentUsesSize = false}) { | 104 | {bool parentUsesSize = false}) { |
| @@ -50,7 +120,13 @@ class Image extends Widget { | @@ -50,7 +120,13 @@ class Image extends Widget { | ||
| 50 | void paint(Context context) { | 120 | void paint(Context context) { |
| 51 | super.paint(context); | 121 | super.paint(context); |
| 52 | 122 | ||
| 53 | - context.canvas.drawImage(image, box.x, box.y, box.width, box.height); | 123 | + _paintImage( |
| 124 | + canvas: context.canvas, | ||
| 125 | + image: image, | ||
| 126 | + rect: box, | ||
| 127 | + alignment: alignment, | ||
| 128 | + fit: fit, | ||
| 129 | + ); | ||
| 54 | } | 130 | } |
| 55 | } | 131 | } |
| 56 | 132 |
| @@ -26,19 +26,20 @@ import 'package:pdf/widgets.dart'; | @@ -26,19 +26,20 @@ import 'package:pdf/widgets.dart'; | ||
| 26 | import 'package:test/test.dart'; | 26 | import 'package:test/test.dart'; |
| 27 | 27 | ||
| 28 | Document pdf; | 28 | Document pdf; |
| 29 | +PdfImage image; | ||
| 29 | 30 | ||
| 30 | void main() { | 31 | void main() { |
| 31 | - setUpAll(() { | 32 | + setUpAll(() async { |
| 32 | Document.debug = true; | 33 | Document.debug = true; |
| 33 | pdf = Document(); | 34 | pdf = Document(); |
| 34 | - }); | ||
| 35 | 35 | ||
| 36 | - test('Pdf Jpeg Download', () async { | ||
| 37 | - final PdfImage image = PdfImage.jpeg( | 36 | + image = PdfImage.jpeg( |
| 38 | pdf.document, | 37 | pdf.document, |
| 39 | image: await download('https://www.nfet.net/nfet.jpg'), | 38 | image: await download('https://www.nfet.net/nfet.jpg'), |
| 40 | ); | 39 | ); |
| 40 | + }); | ||
| 41 | 41 | ||
| 42 | + test('Pdf Jpeg Download', () async { | ||
| 42 | pdf.addPage(Page( | 43 | pdf.addPage(Page( |
| 43 | build: (Context context) => Center(child: Image(image)), | 44 | build: (Context context) => Center(child: Image(image)), |
| 44 | )); | 45 | )); |
| @@ -64,6 +65,25 @@ void main() { | @@ -64,6 +65,25 @@ void main() { | ||
| 64 | ); | 65 | ); |
| 65 | }); | 66 | }); |
| 66 | 67 | ||
| 68 | + test('Pdf Image fit', () async { | ||
| 69 | + pdf.addPage( | ||
| 70 | + MultiPage( | ||
| 71 | + build: (Context context) => | ||
| 72 | + List<Widget>.generate(BoxFit.values.length, (int index) { | ||
| 73 | + final BoxFit fit = BoxFit.values[index]; | ||
| 74 | + return SizedBox( | ||
| 75 | + width: 200, | ||
| 76 | + height: 100, | ||
| 77 | + child: Image( | ||
| 78 | + image, | ||
| 79 | + fit: fit, | ||
| 80 | + ), | ||
| 81 | + ); | ||
| 82 | + }), | ||
| 83 | + ), | ||
| 84 | + ); | ||
| 85 | + }); | ||
| 86 | + | ||
| 67 | tearDownAll(() { | 87 | tearDownAll(() { |
| 68 | final File file = File('jpeg.pdf'); | 88 | final File file = File('jpeg.pdf'); |
| 69 | file.writeAsBytesSync(pdf.save()); | 89 | file.writeAsBytesSync(pdf.save()); |
No preview for this file type
No preview for this file type
-
Please register or login to post a comment