Showing
16 changed files
with
85 additions
and
31 deletions
@@ -194,9 +194,12 @@ public class PrintingHandler implements MethodChannel.MethodCallHandler { | @@ -194,9 +194,12 @@ public class PrintingHandler implements MethodChannel.MethodCallHandler { | ||
194 | 194 | ||
195 | /// The page has been converted to an image | 195 | /// The page has been converted to an image |
196 | @RequiresApi(api = Build.VERSION_CODES.KITKAT) | 196 | @RequiresApi(api = Build.VERSION_CODES.KITKAT) |
197 | - void onPageRasterEnd(PrintingJob printJob) { | 197 | + void onPageRasterEnd(PrintingJob printJob, String error) { |
198 | HashMap<String, Object> args = new HashMap<>(); | 198 | HashMap<String, Object> args = new HashMap<>(); |
199 | args.put("job", printJob.index); | 199 | args.put("job", printJob.index); |
200 | + if (error != null) { | ||
201 | + args.put("error", error); | ||
202 | + } | ||
200 | 203 | ||
201 | channel.invokeMethod("onPageRasterEnd", args); | 204 | channel.invokeMethod("onPageRasterEnd", args); |
202 | } | 205 | } |
@@ -434,8 +434,8 @@ public class PrintingJob extends PrintDocumentAdapter { | @@ -434,8 +434,8 @@ public class PrintingJob extends PrintDocumentAdapter { | ||
434 | 434 | ||
435 | void rasterPdf(final byte[] data, final ArrayList<Integer> pages, final Double scale) { | 435 | void rasterPdf(final byte[] data, final ArrayList<Integer> pages, final Double scale) { |
436 | if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) { | 436 | if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) { |
437 | - Log.e("PDF", "PDF Raster available since Android 5.0 Lollipop (API 21)"); | ||
438 | - printing.onPageRasterEnd(this); | 437 | + printing.onPageRasterEnd( |
438 | + this, "PDF Raster available since Android 5.0 Lollipop (API 21)"); | ||
439 | return; | 439 | return; |
440 | } | 440 | } |
441 | 441 | ||
@@ -443,6 +443,7 @@ public class PrintingJob extends PrintDocumentAdapter { | @@ -443,6 +443,7 @@ public class PrintingJob extends PrintDocumentAdapter { | ||
443 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) | 443 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) |
444 | @Override | 444 | @Override |
445 | public void run() { | 445 | public void run() { |
446 | + String error = null; | ||
446 | try { | 447 | try { |
447 | File file = File.createTempFile("printing", null, null); | 448 | File file = File.createTempFile("printing", null, null); |
448 | FileOutputStream oStream = new FileOutputStream(file); | 449 | FileOutputStream oStream = new FileOutputStream(file); |
@@ -493,12 +494,14 @@ public class PrintingJob extends PrintDocumentAdapter { | @@ -493,12 +494,14 @@ public class PrintingJob extends PrintDocumentAdapter { | ||
493 | 494 | ||
494 | } catch (IOException e) { | 495 | } catch (IOException e) { |
495 | e.printStackTrace(); | 496 | e.printStackTrace(); |
497 | + error = e.getMessage(); | ||
496 | } | 498 | } |
497 | 499 | ||
500 | + final String finalError = error; | ||
498 | new Handler(Looper.getMainLooper()).post(new Runnable() { | 501 | new Handler(Looper.getMainLooper()).post(new Runnable() { |
499 | @Override | 502 | @Override |
500 | public void run() { | 503 | public void run() { |
501 | - printing.onPageRasterEnd(PrintingJob.this); | 504 | + printing.onPageRasterEnd(PrintingJob.this, finalError); |
502 | } | 505 | } |
503 | }); | 506 | }); |
504 | } | 507 | } |
@@ -296,13 +296,17 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -296,13 +296,17 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
296 | 296 | ||
297 | public func rasterPdf(data: Data, pages: [Int]?, scale: CGFloat) { | 297 | public func rasterPdf(data: Data, pages: [Int]?, scale: CGFloat) { |
298 | let provider = CGDataProvider(data: data as CFData)! | 298 | let provider = CGDataProvider(data: data as CFData)! |
299 | - let document = CGPDFDocument(provider)! | 299 | + let document = CGPDFDocument(provider) |
300 | + if document == nil { | ||
301 | + printing.onPageRasterEnd(printJob: self, error: "Cannot raster a malformed PDF file") | ||
302 | + return | ||
303 | + } | ||
300 | 304 | ||
301 | DispatchQueue.global().async { | 305 | DispatchQueue.global().async { |
302 | - let pageCount = document.numberOfPages | 306 | + let pageCount = document!.numberOfPages |
303 | 307 | ||
304 | for pageNum in pages ?? Array(0 ... pageCount - 1) { | 308 | for pageNum in pages ?? Array(0 ... pageCount - 1) { |
305 | - guard let page = document.page(at: pageNum + 1) else { continue } | 309 | + guard let page = document!.page(at: pageNum + 1) else { continue } |
306 | let angle = CGFloat(page.rotationAngle) * CGFloat.pi / -180 | 310 | let angle = CGFloat(page.rotationAngle) * CGFloat.pi / -180 |
307 | let rect = page.getBoxRect(.mediaBox) | 311 | let rect = page.getBoxRect(.mediaBox) |
308 | let width = Int(abs((cos(angle) * rect.width + sin(angle) * rect.height) * scale)) | 312 | let width = Int(abs((cos(angle) * rect.width + sin(angle) * rect.height) * scale)) |
@@ -321,6 +325,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -321,6 +325,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
321 | space: rgb, | 325 | space: rgb, |
322 | bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue | 326 | bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue |
323 | ) | 327 | ) |
328 | + | ||
324 | if context != nil { | 329 | if context != nil { |
325 | context!.translateBy(x: CGFloat(width) / 2, y: CGFloat(height) / 2) | 330 | context!.translateBy(x: CGFloat(width) / 2, y: CGFloat(height) / 2) |
326 | context!.scaleBy(x: scale, y: scale) | 331 | context!.scaleBy(x: scale, y: scale) |
@@ -336,7 +341,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -336,7 +341,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
336 | } | 341 | } |
337 | 342 | ||
338 | DispatchQueue.main.sync { | 343 | DispatchQueue.main.sync { |
339 | - self.printing.onPageRasterEnd(printJob: self) | 344 | + self.printing.onPageRasterEnd(printJob: self, error: nil) |
340 | } | 345 | } |
341 | } | 346 | } |
342 | } | 347 | } |
@@ -349,6 +354,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -349,6 +354,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
349 | "canConvertHtml": true, | 354 | "canConvertHtml": true, |
350 | "canShare": true, | 355 | "canShare": true, |
351 | "canRaster": true, | 356 | "canRaster": true, |
357 | + "canListPrinters": false, | ||
352 | ] | 358 | ] |
353 | return data | 359 | return data |
354 | } | 360 | } |
@@ -193,9 +193,10 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | @@ -193,9 +193,10 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | ||
193 | channel.invokeMethod("onPageRasterized", arguments: data) | 193 | channel.invokeMethod("onPageRasterized", arguments: data) |
194 | } | 194 | } |
195 | 195 | ||
196 | - public func onPageRasterEnd(printJob: PrintJob) { | 196 | + public func onPageRasterEnd(printJob: PrintJob, error: String?) { |
197 | let data: NSDictionary = [ | 197 | let data: NSDictionary = [ |
198 | "job": printJob.index, | 198 | "job": printJob.index, |
199 | + "error": error as Any, | ||
199 | ] | 200 | ] |
200 | channel.invokeMethod("onPageRasterEnd", arguments: data) | 201 | channel.invokeMethod("onPageRasterEnd", arguments: data) |
201 | } | 202 | } |
@@ -130,6 +130,10 @@ class MethodChannelPrinting extends PrintingPlatform { | @@ -130,6 +130,10 @@ class MethodChannelPrinting extends PrintingPlatform { | ||
130 | case 'onPageRasterEnd': | 130 | case 'onPageRasterEnd': |
131 | final job = _printJobs.getJob(call.arguments['job']); | 131 | final job = _printJobs.getJob(call.arguments['job']); |
132 | if (job != null) { | 132 | if (job != null) { |
133 | + final dynamic error = call.arguments['error']; | ||
134 | + if (error != null) { | ||
135 | + job.onPageRasterized!.addError(error); | ||
136 | + } | ||
133 | await job.onPageRasterized!.close(); | 137 | await job.onPageRasterized!.close(); |
134 | _printJobs.remove(job.index); | 138 | _printJobs.remove(job.index); |
135 | } | 139 | } |
@@ -225,6 +225,7 @@ class _PdfPreviewState extends State<PdfPreview> { | @@ -225,6 +225,7 @@ class _PdfPreviewState extends State<PdfPreview> { | ||
225 | }); | 225 | }); |
226 | } | 226 | } |
227 | 227 | ||
228 | + try { | ||
228 | var pageNum = 0; | 229 | var pageNum = 0; |
229 | await for (final PdfRaster page in Printing.raster( | 230 | await for (final PdfRaster page in Printing.raster( |
230 | _doc, | 231 | _doc, |
@@ -252,9 +253,28 @@ class _PdfPreviewState extends State<PdfPreview> { | @@ -252,9 +253,28 @@ class _PdfPreviewState extends State<PdfPreview> { | ||
252 | }); | 253 | }); |
253 | 254 | ||
254 | pageNum++; | 255 | pageNum++; |
256 | + pages.removeRange(pageNum, pages.length); | ||
257 | + } | ||
258 | + } catch (exception, stack) { | ||
259 | + InformationCollector? collector; | ||
260 | + | ||
261 | + assert(() { | ||
262 | + collector = () sync* { | ||
263 | + yield StringProperty('PageFormat', computedPageFormat.toString()); | ||
264 | + }; | ||
265 | + return true; | ||
266 | + }()); | ||
267 | + | ||
268 | + FlutterError.reportError(FlutterErrorDetails( | ||
269 | + exception: exception, | ||
270 | + stack: stack, | ||
271 | + library: 'printing', | ||
272 | + context: ErrorDescription('while generating a PDF'), | ||
273 | + informationCollector: collector, | ||
274 | + )); | ||
275 | + error = exception; | ||
255 | } | 276 | } |
256 | 277 | ||
257 | - pages.removeRange(pageNum, pages.length); | ||
258 | _rastering = false; | 278 | _rastering = false; |
259 | } | 279 | } |
260 | 280 |
@@ -249,7 +249,7 @@ void print_job::raster_pdf(const uint8_t data[], | @@ -249,7 +249,7 @@ void print_job::raster_pdf(const uint8_t data[], | ||
249 | auto doc = FPDF_LoadMemDocument64(data, size, nullptr); | 249 | auto doc = FPDF_LoadMemDocument64(data, size, nullptr); |
250 | if (!doc) { | 250 | if (!doc) { |
251 | FPDF_DestroyLibrary(); | 251 | FPDF_DestroyLibrary(); |
252 | - on_page_raster_end(this); | 252 | + on_page_raster_end(this, "Cannot raster a malformed PDF file"); |
253 | return; | 253 | return; |
254 | } | 254 | } |
255 | 255 | ||
@@ -307,7 +307,7 @@ void print_job::raster_pdf(const uint8_t data[], | @@ -307,7 +307,7 @@ void print_job::raster_pdf(const uint8_t data[], | ||
307 | 307 | ||
308 | FPDF_DestroyLibrary(); | 308 | FPDF_DestroyLibrary(); |
309 | 309 | ||
310 | - on_page_raster_end(this); | 310 | + on_page_raster_end(this, nullptr); |
311 | } | 311 | } |
312 | 312 | ||
313 | FlValue* print_job::printing_info() { | 313 | FlValue* print_job::printing_info() { |
@@ -70,7 +70,7 @@ void on_page_rasterized(print_job* job, | @@ -70,7 +70,7 @@ void on_page_rasterized(print_job* job, | ||
70 | int width, | 70 | int width, |
71 | int height); | 71 | int height); |
72 | 72 | ||
73 | -void on_page_raster_end(print_job* job); | 73 | +void on_page_raster_end(print_job* job, const char* error); |
74 | 74 | ||
75 | void on_layout(print_job* job, | 75 | void on_layout(print_job* job, |
76 | double pageWidth, | 76 | double pageWidth, |
@@ -161,9 +161,12 @@ void on_page_rasterized(print_job* job, | @@ -161,9 +161,12 @@ void on_page_rasterized(print_job* job, | ||
161 | nullptr, nullptr); | 161 | nullptr, nullptr); |
162 | } | 162 | } |
163 | 163 | ||
164 | -void on_page_raster_end(print_job* job) { | 164 | +void on_page_raster_end(print_job* job, const char* error) { |
165 | g_autoptr(FlValue) map = fl_value_new_map(); | 165 | g_autoptr(FlValue) map = fl_value_new_map(); |
166 | fl_value_set_string(map, "job", fl_value_new_int(job->get_id())); | 166 | fl_value_set_string(map, "job", fl_value_new_int(job->get_id())); |
167 | + if (error != nullptr) { | ||
168 | + fl_value_set_string(map, "error", fl_value_new_string(error)); | ||
169 | + } | ||
167 | 170 | ||
168 | fl_method_channel_invoke_method(channel, "onPageRasterEnd", map, nullptr, | 171 | fl_method_channel_invoke_method(channel, "onPageRasterEnd", map, nullptr, |
169 | nullptr, nullptr); | 172 | nullptr, nullptr); |
@@ -242,13 +242,17 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { | @@ -242,13 +242,17 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { | ||
242 | 242 | ||
243 | public func rasterPdf(data: Data, pages: [Int]?, scale: CGFloat) { | 243 | public func rasterPdf(data: Data, pages: [Int]?, scale: CGFloat) { |
244 | let provider = CGDataProvider(data: data as CFData)! | 244 | let provider = CGDataProvider(data: data as CFData)! |
245 | - let document = CGPDFDocument(provider)! | 245 | + let document = CGPDFDocument(provider) |
246 | + if document == nil { | ||
247 | + printing.onPageRasterEnd(printJob: self, error: "Cannot raster a malformed PDF file") | ||
248 | + return | ||
249 | + } | ||
246 | 250 | ||
247 | DispatchQueue.global().async { | 251 | DispatchQueue.global().async { |
248 | - let pageCount = document.numberOfPages | 252 | + let pageCount = document!.numberOfPages |
249 | 253 | ||
250 | for pageNum in pages ?? Array(0 ... pageCount - 1) { | 254 | for pageNum in pages ?? Array(0 ... pageCount - 1) { |
251 | - guard let page = document.page(at: pageNum + 1) else { continue } | 255 | + guard let page = document!.page(at: pageNum + 1) else { continue } |
252 | let angle = CGFloat(page.rotationAngle) * CGFloat.pi / -180 | 256 | let angle = CGFloat(page.rotationAngle) * CGFloat.pi / -180 |
253 | let rect = page.getBoxRect(.mediaBox) | 257 | let rect = page.getBoxRect(.mediaBox) |
254 | let width = Int(abs((cos(angle) * rect.width + sin(angle) * rect.height) * scale)) | 258 | let width = Int(abs((cos(angle) * rect.width + sin(angle) * rect.height) * scale)) |
@@ -283,7 +287,7 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { | @@ -283,7 +287,7 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { | ||
283 | } | 287 | } |
284 | 288 | ||
285 | DispatchQueue.main.sync { | 289 | DispatchQueue.main.sync { |
286 | - self.printing.onPageRasterEnd(printJob: self) | 290 | + self.printing.onPageRasterEnd(printJob: self, error: nil) |
287 | } | 291 | } |
288 | } | 292 | } |
289 | } | 293 | } |
@@ -291,7 +295,7 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { | @@ -291,7 +295,7 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { | ||
291 | public static func printingInfo() -> NSDictionary { | 295 | public static func printingInfo() -> NSDictionary { |
292 | let data: NSDictionary = [ | 296 | let data: NSDictionary = [ |
293 | "directPrint": true, | 297 | "directPrint": true, |
294 | - "dynamicLayout": false, | 298 | + "dynamicLayout": true, |
295 | "canPrint": true, | 299 | "canPrint": true, |
296 | "canConvertHtml": true, | 300 | "canConvertHtml": true, |
297 | "canShare": true, | 301 | "canShare": true, |
@@ -188,9 +188,10 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | @@ -188,9 +188,10 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | ||
188 | channel.invokeMethod("onPageRasterized", arguments: data) | 188 | channel.invokeMethod("onPageRasterized", arguments: data) |
189 | } | 189 | } |
190 | 190 | ||
191 | - public func onPageRasterEnd(printJob: PrintJob) { | 191 | + public func onPageRasterEnd(printJob: PrintJob, error: String?) { |
192 | let data: NSDictionary = [ | 192 | let data: NSDictionary = [ |
193 | "job": printJob.index, | 193 | "job": printJob.index, |
194 | + "error": error as Any, | ||
194 | ] | 195 | ] |
195 | channel.invokeMethod("onPageRasterEnd", arguments: data) | 196 | channel.invokeMethod("onPageRasterEnd", arguments: data) |
196 | } | 197 | } |
@@ -7,7 +7,7 @@ description: > | @@ -7,7 +7,7 @@ description: > | ||
7 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/printing | 7 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/printing |
8 | repository: https://github.com/DavBfr/dart_pdf | 8 | repository: https://github.com/DavBfr/dart_pdf |
9 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues | 9 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues |
10 | -version: 5.2.1 | 10 | +version: 5.2.2 |
11 | 11 | ||
12 | environment: | 12 | environment: |
13 | sdk: ">=2.12.0-0 <3.0.0" | 13 | sdk: ">=2.12.0-0 <3.0.0" |
@@ -289,7 +289,7 @@ void PrintJob::rasterPdf(std::vector<uint8_t> data, | @@ -289,7 +289,7 @@ void PrintJob::rasterPdf(std::vector<uint8_t> data, | ||
289 | auto doc = FPDF_LoadMemDocument64(data.data(), data.size(), nullptr); | 289 | auto doc = FPDF_LoadMemDocument64(data.data(), data.size(), nullptr); |
290 | if (!doc) { | 290 | if (!doc) { |
291 | FPDF_DestroyLibrary(); | 291 | FPDF_DestroyLibrary(); |
292 | - printing->onPageRasterEnd(this); | 292 | + printing->onPageRasterEnd(this, "Cannot raster a malformed PDF file"); |
293 | return; | 293 | return; |
294 | } | 294 | } |
295 | 295 | ||
@@ -347,7 +347,7 @@ void PrintJob::rasterPdf(std::vector<uint8_t> data, | @@ -347,7 +347,7 @@ void PrintJob::rasterPdf(std::vector<uint8_t> data, | ||
347 | 347 | ||
348 | FPDF_DestroyLibrary(); | 348 | FPDF_DestroyLibrary(); |
349 | 349 | ||
350 | - printing->onPageRasterEnd(this); | 350 | + printing->onPageRasterEnd(this, nullptr); |
351 | } | 351 | } |
352 | 352 | ||
353 | std::map<std::string, bool> PrintJob::printingInfo() { | 353 | std::map<std::string, bool> PrintJob::printingInfo() { |
@@ -44,13 +44,18 @@ void Printing::onPageRasterized(std::vector<uint8_t> data, | @@ -44,13 +44,18 @@ void Printing::onPageRasterized(std::vector<uint8_t> data, | ||
44 | }))); | 44 | }))); |
45 | } | 45 | } |
46 | 46 | ||
47 | -void Printing::onPageRasterEnd(PrintJob* job) { | ||
48 | - channel->InvokeMethod("onPageRasterEnd", | ||
49 | - std::make_unique<flutter::EncodableValue>( | ||
50 | - flutter::EncodableValue(flutter::EncodableMap{ | ||
51 | - {flutter::EncodableValue("job"), | ||
52 | - flutter::EncodableValue(job->id())}, | ||
53 | - }))); | 47 | +void Printing::onPageRasterEnd(PrintJob* job, const char* error) { |
48 | + auto map = flutter::EncodableMap{ | ||
49 | + {flutter::EncodableValue("job"), flutter::EncodableValue(job->id())}, | ||
50 | + }; | ||
51 | + | ||
52 | + if (!error.empty()) { | ||
53 | + map[flutter::EncodableValue("error")] = flutter::EncodableValue(error); | ||
54 | + } | ||
55 | + | ||
56 | + channel->InvokeMethod( | ||
57 | + "onPageRasterEnd", | ||
58 | + std::make_unique<flutter::EncodableValue>(flutter::EncodableValue(map))); | ||
54 | } | 59 | } |
55 | 60 | ||
56 | class OnLayoutResult : public flutter::MethodResult<flutter::EncodableValue> { | 61 | class OnLayoutResult : public flutter::MethodResult<flutter::EncodableValue> { |
@@ -40,7 +40,7 @@ class Printing { | @@ -40,7 +40,7 @@ class Printing { | ||
40 | int height, | 40 | int height, |
41 | PrintJob* job); | 41 | PrintJob* job); |
42 | 42 | ||
43 | - void onPageRasterEnd(PrintJob* job); | 43 | + void onPageRasterEnd(PrintJob* job, const char* error); |
44 | 44 | ||
45 | void onLayout(PrintJob* job, | 45 | void onLayout(PrintJob* job, |
46 | double pageWidth, | 46 | double pageWidth, |
-
Please register or login to post a comment