David PHAM-VAN

Fix Image fit

@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 4
5 - Update dependency to barcode ^1.5.0 5 - Update dependency to barcode ^1.5.0
6 - Update type1 font warning url 6 - Update type1 font warning url
  7 +- Fix Image fit
7 8
8 ## 1.4.0 9 ## 1.4.0
9 10
@@ -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