Showing
4 changed files
with
115 additions
and
9 deletions
@@ -46,16 +46,15 @@ doc.addPage(pw.Page( | @@ -46,16 +46,15 @@ doc.addPage(pw.Page( | ||
46 | pageFormat: PdfPageFormat.a4, | 46 | pageFormat: PdfPageFormat.a4, |
47 | build: (pw.Context context) { | 47 | build: (pw.Context context) { |
48 | return pw.Center( | 48 | return pw.Center( |
49 | - child: pw.Text("Hello World"), | 49 | + child: pw.Text('Hello World'), |
50 | ); // Center | 50 | ); // Center |
51 | })); // Page | 51 | })); // Page |
52 | ``` | 52 | ``` |
53 | 53 | ||
54 | -To load an image from an ImageProvider: | 54 | +To load an image from a Flutter asset: |
55 | 55 | ||
56 | ```dart | 56 | ```dart |
57 | -const imageProvider = const AssetImage('assets/image.png'); | ||
58 | -final image = await flutterImageProvider(imageProvider); | 57 | +final image = await imageFromAssetBundle('assets/image.png'); |
59 | 58 | ||
60 | doc.addPage(pw.Page( | 59 | doc.addPage(pw.Page( |
61 | build: (pw.Context context) { | 60 | build: (pw.Context context) { |
@@ -68,8 +67,7 @@ doc.addPage(pw.Page( | @@ -68,8 +67,7 @@ doc.addPage(pw.Page( | ||
68 | To use a TrueType font from a flutter bundle: | 67 | To use a TrueType font from a flutter bundle: |
69 | 68 | ||
70 | ```dart | 69 | ```dart |
71 | -final font = await rootBundle.load("assets/open-sans.ttf"); | ||
72 | -final ttf = pw.Font.ttf(font); | 70 | +final ttf = await fontFromAssetBundle('assets/open-sans.ttf'); |
73 | 71 | ||
74 | doc.addPage(pw.Page( | 72 | doc.addPage(pw.Page( |
75 | build: (pw.Context context) { | 73 | build: (pw.Context context) { |
@@ -83,7 +81,7 @@ To save the pdf file using the [path_provider](https://pub.dev/packages/path_pro | @@ -83,7 +81,7 @@ To save the pdf file using the [path_provider](https://pub.dev/packages/path_pro | ||
83 | 81 | ||
84 | ```dart | 82 | ```dart |
85 | final output = await getTemporaryDirectory(); | 83 | final output = await getTemporaryDirectory(); |
86 | -final file = File("${output.path}/example.pdf"); | 84 | +final file = File('${output.path}/example.pdf'); |
87 | await file.writeAsBytes(await doc.save()); | 85 | await file.writeAsBytes(await doc.save()); |
88 | ``` | 86 | ``` |
89 | 87 |
@@ -15,10 +15,13 @@ | @@ -15,10 +15,13 @@ | ||
15 | */ | 15 | */ |
16 | 16 | ||
17 | import 'dart:async'; | 17 | import 'dart:async'; |
18 | +import 'dart:io'; | ||
19 | +import 'dart:typed_data'; | ||
18 | import 'dart:ui' as ui; | 20 | import 'dart:ui' as ui; |
19 | 21 | ||
20 | import 'package:flutter/rendering.dart' as rdr; | 22 | import 'package:flutter/rendering.dart' as rdr; |
21 | import 'package:flutter/services.dart'; | 23 | import 'package:flutter/services.dart'; |
24 | +import 'package:pdf/pdf.dart'; | ||
22 | import 'package:pdf/widgets.dart'; | 25 | import 'package:pdf/widgets.dart'; |
23 | 26 | ||
24 | /// Loads an image from a Flutter [ImageProvider] | 27 | /// Loads an image from a Flutter [ImageProvider] |
@@ -63,7 +66,108 @@ Future<ImageProvider> flutterImageProvider( | @@ -63,7 +66,108 @@ Future<ImageProvider> flutterImageProvider( | ||
63 | 66 | ||
64 | /// Loads a font from an asset bundle key. If used multiple times with the same font name, | 67 | /// Loads a font from an asset bundle key. If used multiple times with the same font name, |
65 | /// it will be included multiple times in the pdf file | 68 | /// it will be included multiple times in the pdf file |
66 | -Future<TtfFont> fontFromAssetBundle(String key, AssetBundle bundle) async { | 69 | +Future<TtfFont> fontFromAssetBundle(String key, [AssetBundle? bundle]) async { |
70 | + bundle ??= rootBundle; | ||
67 | final data = await bundle.load(key); | 71 | final data = await bundle.load(key); |
68 | return TtfFont(data); | 72 | return TtfFont(data); |
69 | } | 73 | } |
74 | + | ||
75 | +/// Load an image from an asset bundle key. | ||
76 | +Future<ImageProvider> imageFromAssetBundle(String key, | ||
77 | + [AssetBundle? bundle]) async { | ||
78 | + bundle ??= rootBundle; | ||
79 | + final data = await bundle.load(key); | ||
80 | + return MemoryImage(data.buffer.asUint8List()); | ||
81 | +} | ||
82 | + | ||
83 | +final HttpClient _sharedHttpClient = HttpClient(); | ||
84 | + | ||
85 | +/// Store network images in a cache | ||
86 | +abstract class PdfBaseImageCache { | ||
87 | + /// Create a network image cache | ||
88 | + const PdfBaseImageCache(); | ||
89 | + | ||
90 | + /// The default cache used when none specified | ||
91 | + static final defaultCache = PdfMemoryImageCache(); | ||
92 | + | ||
93 | + /// Add an image to the cache | ||
94 | + Future<void> add(String key, Uint8List bytes); | ||
95 | + | ||
96 | + /// Retrieve an image from the cache | ||
97 | + Future<Uint8List?> get(String key); | ||
98 | + | ||
99 | + /// Does the cache contains this image? | ||
100 | + Future<bool> contains(String key); | ||
101 | + | ||
102 | + /// Remove an image from the cache | ||
103 | + Future<void> remove(String key); | ||
104 | + | ||
105 | + /// Clear the cache | ||
106 | + Future<void> clear(); | ||
107 | +} | ||
108 | + | ||
109 | +/// Memory image cache | ||
110 | +class PdfMemoryImageCache extends PdfBaseImageCache { | ||
111 | + /// Create a memory image cache | ||
112 | + PdfMemoryImageCache(); | ||
113 | + | ||
114 | + final _imageCache = <String, Uint8List>{}; | ||
115 | + | ||
116 | + @override | ||
117 | + Future<void> add(String key, Uint8List bytes) async { | ||
118 | + _imageCache[key] = bytes; | ||
119 | + } | ||
120 | + | ||
121 | + @override | ||
122 | + Future<Uint8List?> get(String key) async { | ||
123 | + return _imageCache[key]; | ||
124 | + } | ||
125 | + | ||
126 | + @override | ||
127 | + Future<void> clear() async { | ||
128 | + _imageCache.clear(); | ||
129 | + } | ||
130 | + | ||
131 | + @override | ||
132 | + Future<bool> contains(String key) async { | ||
133 | + return _imageCache.containsKey(key); | ||
134 | + } | ||
135 | + | ||
136 | + @override | ||
137 | + Future<void> remove(String key) async { | ||
138 | + _imageCache.remove(key); | ||
139 | + } | ||
140 | +} | ||
141 | + | ||
142 | +/// Download an image from the network. | ||
143 | +Future<ImageProvider> networkImage( | ||
144 | + String url, { | ||
145 | + bool cache = true, | ||
146 | + Map<String, String>? headers, | ||
147 | + PdfImageOrientation? orientation, | ||
148 | + double? dpi, | ||
149 | + PdfBaseImageCache? imageCache, | ||
150 | +}) async { | ||
151 | + imageCache ??= PdfBaseImageCache.defaultCache; | ||
152 | + | ||
153 | + if (cache && await imageCache.contains(url)) { | ||
154 | + return MemoryImage((await imageCache.get(url))!, | ||
155 | + orientation: orientation, dpi: dpi); | ||
156 | + } | ||
157 | + | ||
158 | + final request = await _sharedHttpClient.getUrl(Uri.parse(url)); | ||
159 | + headers?.forEach((String name, String value) { | ||
160 | + request.headers.add(name, value); | ||
161 | + }); | ||
162 | + final response = await request.close(); | ||
163 | + final builder = await response.fold( | ||
164 | + BytesBuilder(), (BytesBuilder b, List<int> d) => b..add(d)); | ||
165 | + final List<int> data = builder.takeBytes(); | ||
166 | + final bytes = Uint8List.fromList(data); | ||
167 | + | ||
168 | + if (cache) { | ||
169 | + await imageCache.add(url, bytes); | ||
170 | + } | ||
171 | + | ||
172 | + return MemoryImage(bytes, orientation: orientation, dpi: dpi); | ||
173 | +} |
@@ -4,7 +4,7 @@ description: Plugin that allows Flutter apps to generate and print documents to | @@ -4,7 +4,7 @@ description: Plugin that allows Flutter apps to generate and print documents to | ||
4 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/printing | 4 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/printing |
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: 5.0.0-nullsafety.1 | 7 | +version: 5.0.0-nullsafety.2 |
8 | 8 | ||
9 | environment: | 9 | environment: |
10 | sdk: ">=2.12.0-0 <3.0.0" | 10 | sdk: ">=2.12.0-0 <3.0.0" |
-
Please register or login to post a comment