Showing
8 changed files
with
202 additions
and
77 deletions
@@ -5,6 +5,7 @@ | @@ -5,6 +5,7 @@ | ||
5 | - Add imageFromAssetBundle and networkImage | 5 | - Add imageFromAssetBundle and networkImage |
6 | - Add Page orientation on PdfPreview | 6 | - Add Page orientation on PdfPreview |
7 | - Improve PrintJob object | 7 | - Improve PrintJob object |
8 | +- Implement dynamic layout on iOS and macOS | ||
8 | 9 | ||
9 | ## 5.0.0-nullsafety.1 | 10 | ## 5.0.0-nullsafety.1 |
10 | 11 |
@@ -28,6 +28,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -28,6 +28,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
28 | private var urlObservation: NSKeyValueObservation? | 28 | private var urlObservation: NSKeyValueObservation? |
29 | private var jobName: String? | 29 | private var jobName: String? |
30 | private var orientation: UIPrintInfo.Orientation? | 30 | private var orientation: UIPrintInfo.Orientation? |
31 | + private let semaphore = DispatchSemaphore(value: 0) | ||
31 | 32 | ||
32 | public init(printing: PrintingPlugin, index: Int) { | 33 | public init(printing: PrintingPlugin, index: Int) { |
33 | self.printing = printing | 34 | self.printing = printing |
@@ -46,9 +47,9 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -46,9 +47,9 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
46 | } | 47 | } |
47 | } | 48 | } |
48 | 49 | ||
49 | - func cancelJob(_ error: String?) { | 50 | + func cancelJob(_: String?) { |
50 | pdfDocument = nil | 51 | pdfDocument = nil |
51 | - printing.onCompleted(printJob: self, completed: false, error: error as NSString?) | 52 | + semaphore.signal() |
52 | } | 53 | } |
53 | 54 | ||
54 | func setDocument(_ data: Data?) { | 55 | func setDocument(_ data: Data?) { |
@@ -57,24 +58,25 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -57,24 +58,25 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
57 | let dataProvider = CGDataProvider(dataInfo: nil, data: bytesPointer, size: data?.count ?? 0, releaseData: dataProviderReleaseDataCallback) | 58 | let dataProvider = CGDataProvider(dataInfo: nil, data: bytesPointer, size: data?.count ?? 0, releaseData: dataProviderReleaseDataCallback) |
58 | pdfDocument = CGPDFDocument(dataProvider!) | 59 | pdfDocument = CGPDFDocument(dataProvider!) |
59 | 60 | ||
60 | - let controller = UIPrintInteractionController.shared | ||
61 | - controller.delegate = self | ||
62 | - | ||
63 | - let printInfo = UIPrintInfo.printInfo() | ||
64 | - printInfo.jobName = jobName! | ||
65 | - printInfo.outputType = .general | ||
66 | - if orientation != nil { | ||
67 | - printInfo.orientation = orientation! | ||
68 | - orientation = nil | ||
69 | - } | ||
70 | - controller.printInfo = printInfo | ||
71 | - controller.printPageRenderer = self | ||
72 | - controller.present(animated: true, completionHandler: completionHandler) | 61 | + // Unblock the main thread |
62 | + semaphore.signal() | ||
73 | } | 63 | } |
74 | 64 | ||
75 | override public var numberOfPages: Int { | 65 | override public var numberOfPages: Int { |
76 | - let pages = pdfDocument?.numberOfPages ?? 0 | ||
77 | - return pages | 66 | + printing.onLayout( |
67 | + printJob: self, | ||
68 | + width: paperRect.size.width, | ||
69 | + height: paperRect.size.height, | ||
70 | + marginLeft: printableRect.origin.x, | ||
71 | + marginTop: printableRect.origin.y, | ||
72 | + marginRight: paperRect.size.width - (printableRect.origin.x + printableRect.size.width), | ||
73 | + marginBottom: paperRect.size.height - (printableRect.origin.y + printableRect.size.height) | ||
74 | + ) | ||
75 | + | ||
76 | + // Block the main thread, waiting for a document | ||
77 | + semaphore.wait() | ||
78 | + | ||
79 | + return pdfDocument?.numberOfPages ?? 0 | ||
78 | } | 80 | } |
79 | 81 | ||
80 | func completionHandler(printController _: UIPrintInteractionController, completed: Bool, error: Error?) { | 82 | func completionHandler(printController _: UIPrintInteractionController, completed: Bool, error: Error?) { |
@@ -110,7 +112,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -110,7 +112,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
110 | controller.print(to: printer, completionHandler: completionHandler) | 112 | controller.print(to: printer, completionHandler: completionHandler) |
111 | } | 113 | } |
112 | 114 | ||
113 | - func printPdf(name: String, withPageSize size: CGSize, andMargin margin: CGRect) { | 115 | + func printPdf(name: String, withPageSize size: CGSize, andMargin _: CGRect) { |
114 | let printing = UIPrintInteractionController.isPrintingAvailable | 116 | let printing = UIPrintInteractionController.isPrintingAvailable |
115 | if !printing { | 117 | if !printing { |
116 | self.printing.onCompleted(printJob: self, completed: false, error: "Printing not available") | 118 | self.printing.onCompleted(printJob: self, completed: false, error: "Printing not available") |
@@ -123,15 +125,21 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -123,15 +125,21 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
123 | 125 | ||
124 | jobName = name | 126 | jobName = name |
125 | 127 | ||
126 | - self.printing.onLayout( | ||
127 | - printJob: self, | ||
128 | - width: size.width, | ||
129 | - height: size.height, | ||
130 | - marginLeft: margin.minX, | ||
131 | - marginTop: margin.minY, | ||
132 | - marginRight: size.width - margin.maxX, | ||
133 | - marginBottom: size.height - margin.maxY | ||
134 | - ) | 128 | + let controller = UIPrintInteractionController.shared |
129 | + controller.delegate = self | ||
130 | + | ||
131 | + let printInfo = UIPrintInfo.printInfo() | ||
132 | + printInfo.jobName = jobName! | ||
133 | + printInfo.outputType = .general | ||
134 | + if orientation != nil { | ||
135 | + printInfo.orientation = orientation! | ||
136 | + orientation = nil | ||
137 | + } | ||
138 | + controller.printInfo = printInfo | ||
139 | + controller.showsPaperSelectionForLoadedPapers = true | ||
140 | + | ||
141 | + controller.printPageRenderer = self | ||
142 | + controller.present(animated: true, completionHandler: completionHandler) | ||
135 | } | 143 | } |
136 | 144 | ||
137 | static func sharePdf(data: Data, withSourceRect rect: CGRect, andName name: String) { | 145 | static func sharePdf(data: Data, withSourceRect rect: CGRect, andName name: String) { |
@@ -287,7 +295,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -287,7 +295,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
287 | public static func printingInfo() -> NSDictionary { | 295 | public static func printingInfo() -> NSDictionary { |
288 | let data: NSDictionary = [ | 296 | let data: NSDictionary = [ |
289 | "directPrint": true, | 297 | "directPrint": true, |
290 | - "dynamicLayout": false, | 298 | + "dynamicLayout": true, |
291 | "canPrint": true, | 299 | "canPrint": true, |
292 | "canConvertHtml": true, | 300 | "canConvertHtml": true, |
293 | "canShare": true, | 301 | "canShare": true, |
@@ -17,12 +17,29 @@ | @@ -17,12 +17,29 @@ | ||
17 | import Flutter | 17 | import Flutter |
18 | import Foundation | 18 | import Foundation |
19 | 19 | ||
20 | +// Dart:ffi API | ||
21 | +private var _printingPlugin: PrintingPlugin? | ||
22 | + | ||
23 | +@_cdecl("net_nfet_printing_set_document") | ||
24 | +func setDocument(job: UInt32, doc: UnsafePointer<UInt8>, size: UInt64) { | ||
25 | + _printingPlugin!.jobs[job]?.setDocument(Data(bytes: doc, count: Int(size))) | ||
26 | +} | ||
27 | + | ||
28 | +@_cdecl("net_nfet_printing_set_error") | ||
29 | +func setError(job: UInt32, message: UnsafePointer<CChar>) { | ||
30 | + _printingPlugin!.jobs[job]?.cancelJob(String(cString: message)) | ||
31 | +} | ||
32 | + | ||
33 | +// End of Dart:ffi API | ||
34 | + | ||
20 | public class PrintingPlugin: NSObject, FlutterPlugin { | 35 | public class PrintingPlugin: NSObject, FlutterPlugin { |
21 | private var channel: FlutterMethodChannel | 36 | private var channel: FlutterMethodChannel |
37 | + public var jobs = [UInt32: PrintJob]() | ||
22 | 38 | ||
23 | init(_ channel: FlutterMethodChannel) { | 39 | init(_ channel: FlutterMethodChannel) { |
24 | self.channel = channel | 40 | self.channel = channel |
25 | super.init() | 41 | super.init() |
42 | + _printingPlugin = self | ||
26 | } | 43 | } |
27 | 44 | ||
28 | /// Entry point | 45 | /// Entry point |
@@ -44,6 +61,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | @@ -44,6 +61,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | ||
44 | let marginRight = CGFloat((args["marginRight"] as? NSNumber)?.floatValue ?? 0.0) | 61 | let marginRight = CGFloat((args["marginRight"] as? NSNumber)?.floatValue ?? 0.0) |
45 | let marginBottom = CGFloat((args["marginBottom"] as? NSNumber)?.floatValue ?? 0.0) | 62 | let marginBottom = CGFloat((args["marginBottom"] as? NSNumber)?.floatValue ?? 0.0) |
46 | let printJob = PrintJob(printing: self, index: args["job"] as! Int) | 63 | let printJob = PrintJob(printing: self, index: args["job"] as! Int) |
64 | + jobs[args["job"] as! UInt32] = printJob | ||
47 | printJob.printPdf(name: name, | 65 | printJob.printPdf(name: name, |
48 | withPageSize: CGSize( | 66 | withPageSize: CGSize( |
49 | width: width, | 67 | width: width, |
@@ -137,19 +155,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | @@ -137,19 +155,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | ||
137 | "job": printJob.index, | 155 | "job": printJob.index, |
138 | ] as [String: Any] | 156 | ] as [String: Any] |
139 | 157 | ||
140 | - channel.invokeMethod("onLayout", arguments: arg, result: { (result: Any?) -> Void in | ||
141 | - if result as? Bool == false { | ||
142 | - printJob.cancelJob(nil) | ||
143 | - } else if result is FlutterError { | ||
144 | - let error = result as! FlutterError | ||
145 | - printJob.cancelJob(error.message) | ||
146 | - } else if result is FlutterStandardTypedData { | ||
147 | - let object = result as! FlutterStandardTypedData | ||
148 | - printJob.setDocument(object.data) | ||
149 | - } else { | ||
150 | - printJob.cancelJob("Unknown data type") | ||
151 | - } | ||
152 | - }) | 158 | + channel.invokeMethod("onLayout", arguments: arg) |
153 | } | 159 | } |
154 | 160 | ||
155 | /// send completion status to flutter | 161 | /// send completion status to flutter |
@@ -160,6 +166,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | @@ -160,6 +166,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | ||
160 | "job": printJob.index, | 166 | "job": printJob.index, |
161 | ] | 167 | ] |
162 | channel.invokeMethod("onCompleted", arguments: data) | 168 | channel.invokeMethod("onCompleted", arguments: data) |
169 | + jobs.removeValue(forKey: UInt32(printJob.index)) | ||
163 | } | 170 | } |
164 | 171 | ||
165 | /// send html to pdf data result to flutter | 172 | /// send html to pdf data result to flutter |
@@ -15,11 +15,13 @@ | @@ -15,11 +15,13 @@ | ||
15 | */ | 15 | */ |
16 | 16 | ||
17 | import 'dart:async'; | 17 | import 'dart:async'; |
18 | +import 'dart:io'; | ||
18 | import 'dart:typed_data'; | 19 | import 'dart:typed_data'; |
19 | 20 | ||
20 | import 'package:flutter/rendering.dart' show Rect; | 21 | import 'package:flutter/rendering.dart' show Rect; |
21 | import 'package:flutter/services.dart'; | 22 | import 'package:flutter/services.dart'; |
22 | import 'package:pdf/pdf.dart'; | 23 | import 'package:pdf/pdf.dart'; |
24 | +import 'package:printing/src/method_channel_ffi.dart'; | ||
23 | 25 | ||
24 | import 'callback.dart'; | 26 | import 'callback.dart'; |
25 | import 'interface.dart'; | 27 | import 'interface.dart'; |
@@ -56,7 +58,20 @@ class MethodChannelPrinting extends PrintingPlatform { | @@ -56,7 +58,20 @@ class MethodChannelPrinting extends PrintingPlatform { | ||
56 | marginBottom: call.arguments['marginBottom'], | 58 | marginBottom: call.arguments['marginBottom'], |
57 | ); | 59 | ); |
58 | 60 | ||
59 | - final bytes = await job.onLayout!(format); | 61 | + Uint8List bytes; |
62 | + try { | ||
63 | + bytes = await job.onLayout!(format); | ||
64 | + } catch (e) { | ||
65 | + if (Platform.isMacOS || Platform.isIOS) { | ||
66 | + return setErrorFfi(job, e.toString()); | ||
67 | + } | ||
68 | + | ||
69 | + rethrow; | ||
70 | + } | ||
71 | + | ||
72 | + if (Platform.isMacOS || Platform.isIOS) { | ||
73 | + return setDocumentFfi(job, bytes); | ||
74 | + } | ||
60 | 75 | ||
61 | return Uint8List.fromList(bytes); | 76 | return Uint8List.fromList(bytes); |
62 | case 'onCompleted': | 77 | case 'onCompleted': |
printing/lib/src/method_channel_ffi.dart
0 → 100644
1 | +/* | ||
2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +import 'dart:ffi' as ffi; | ||
18 | +import 'dart:io' as io; | ||
19 | +import 'dart:typed_data'; | ||
20 | + | ||
21 | +import 'package:ffi/ffi.dart' as ffi; | ||
22 | + | ||
23 | +import 'print_job.dart'; | ||
24 | + | ||
25 | +/// Load the dynamic library | ||
26 | +final ffi.DynamicLibrary _dynamicLibrary = _open(); | ||
27 | +ffi.DynamicLibrary _open() { | ||
28 | + if (io.Platform.isMacOS || io.Platform.isIOS) { | ||
29 | + return ffi.DynamicLibrary.process(); | ||
30 | + } | ||
31 | + throw UnsupportedError('This platform is not supported.'); | ||
32 | +} | ||
33 | + | ||
34 | +/// Set the Pdf document data | ||
35 | +void setDocumentFfi(PrintJob job, Uint8List data) { | ||
36 | + final nativeBytes = ffi.allocate<ffi.Uint8>(count: data.length); | ||
37 | + nativeBytes.asTypedList(data.length).setAll(0, data); | ||
38 | + _setDocument(job.index, nativeBytes, data.length); | ||
39 | +} | ||
40 | + | ||
41 | +final _SetDocument_Dart _setDocument = | ||
42 | + _dynamicLibrary.lookupFunction<_SetDocument_C, _SetDocument_Dart>( | ||
43 | + 'net_nfet_printing_set_document', | ||
44 | +); | ||
45 | + | ||
46 | +typedef _SetDocument_C = ffi.Void Function( | ||
47 | + ffi.Uint32 job, | ||
48 | + ffi.Pointer<ffi.Uint8> data, | ||
49 | + ffi.Uint64 size, | ||
50 | +); | ||
51 | + | ||
52 | +typedef _SetDocument_Dart = void Function( | ||
53 | + int job, | ||
54 | + ffi.Pointer<ffi.Uint8> data, | ||
55 | + int size, | ||
56 | +); | ||
57 | + | ||
58 | +/// Set the Pdf Error message | ||
59 | +void setErrorFfi(PrintJob job, String message) { | ||
60 | + _setError(job.index, ffi.Utf8.toUtf8(message)); | ||
61 | +} | ||
62 | + | ||
63 | +final _SetError_Dart _setError = | ||
64 | + _dynamicLibrary.lookupFunction<_SetError_C, _SetError_Dart>( | ||
65 | + 'net_nfet_printing_set_error', | ||
66 | +); | ||
67 | + | ||
68 | +typedef _SetError_C = ffi.Void Function( | ||
69 | + ffi.Uint32 job, | ||
70 | + ffi.Pointer<ffi.Utf8> message, | ||
71 | +); | ||
72 | + | ||
73 | +typedef _SetError_Dart = void Function( | ||
74 | + int job, | ||
75 | + ffi.Pointer<ffi.Utf8> message, | ||
76 | +); |
@@ -29,6 +29,7 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { | @@ -29,6 +29,7 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { | ||
29 | private var printOperation: NSPrintOperation? | 29 | private var printOperation: NSPrintOperation? |
30 | private var pdfDocument: CGPDFDocument? | 30 | private var pdfDocument: CGPDFDocument? |
31 | private var page: CGPDFPage? | 31 | private var page: CGPDFPage? |
32 | + private let semaphore = DispatchSemaphore(value: 0) | ||
32 | 33 | ||
33 | public init(printing: PrintingPlugin, index: Int) { | 34 | public init(printing: PrintingPlugin, index: Int) { |
34 | self.printing = printing | 35 | self.printing = printing |
@@ -47,7 +48,29 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { | @@ -47,7 +48,29 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { | ||
47 | 48 | ||
48 | setFrameSize(size) | 49 | setFrameSize(size) |
49 | setBoundsSize(size) | 50 | setBoundsSize(size) |
50 | - range.pointee.length = pdfDocument?.numberOfPages ?? 0 | 51 | + |
52 | + printing.onLayout( | ||
53 | + printJob: self, | ||
54 | + width: printOperation!.printInfo.paperSize.width, | ||
55 | + height: printOperation!.printInfo.paperSize.height, | ||
56 | + marginLeft: printOperation!.printInfo.leftMargin, | ||
57 | + marginTop: printOperation!.printInfo.topMargin, | ||
58 | + marginRight: printOperation!.printInfo.rightMargin, | ||
59 | + marginBottom: printOperation!.printInfo.bottomMargin | ||
60 | + ) | ||
61 | + | ||
62 | + // Block the main thread, waiting for a document | ||
63 | + semaphore.wait() | ||
64 | + | ||
65 | + if pdfDocument != nil { | ||
66 | + range.pointee.length = pdfDocument!.numberOfPages | ||
67 | + let page = pdfDocument!.page(at: 1) | ||
68 | + let size = page?.getBoxRect(CGPDFBox.mediaBox) ?? NSZeroRect | ||
69 | + setFrameSize(size.size) | ||
70 | + setBoundsSize(size.size) | ||
71 | + } else { | ||
72 | + range.pointee.length = 0 | ||
73 | + } | ||
51 | return true | 74 | return true |
52 | } | 75 | } |
53 | 76 | ||
@@ -67,8 +90,8 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { | @@ -67,8 +90,8 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { | ||
67 | let dataProvider = CGDataProvider(dataInfo: nil, data: bytesPointer, size: data?.count ?? 0, releaseData: dataProviderReleaseDataCallback) | 90 | let dataProvider = CGDataProvider(dataInfo: nil, data: bytesPointer, size: data?.count ?? 0, releaseData: dataProviderReleaseDataCallback) |
68 | pdfDocument = CGPDFDocument(dataProvider!) | 91 | pdfDocument = CGPDFDocument(dataProvider!) |
69 | 92 | ||
70 | - let window = NSApplication.shared.mainWindow! | ||
71 | - printOperation!.runModal(for: window, delegate: self, didRun: #selector(printOperationDidRun(printOperation:success:contextInfo:)), contextInfo: nil) | 93 | + // Unblock the main thread |
94 | + semaphore.signal() | ||
72 | } | 95 | } |
73 | 96 | ||
74 | override public func draw(_: NSRect) { | 97 | override public func draw(_: NSRect) { |
@@ -136,21 +159,15 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { | @@ -136,21 +159,15 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { | ||
136 | // Print the custom view | 159 | // Print the custom view |
137 | printOperation = NSPrintOperation(view: self, printInfo: printInfo) | 160 | printOperation = NSPrintOperation(view: self, printInfo: printInfo) |
138 | printOperation!.jobTitle = name | 161 | printOperation!.jobTitle = name |
139 | - printOperation!.printPanel.options = [.showsPreview] | 162 | + printOperation!.printPanel.options = [.showsPreview, .showsPaperSize, .showsOrientation] |
140 | 163 | ||
141 | - printing.onLayout( | ||
142 | - printJob: self, | ||
143 | - width: printOperation!.printInfo.paperSize.width, | ||
144 | - height: printOperation!.printInfo.paperSize.height, | ||
145 | - marginLeft: printOperation!.printInfo.leftMargin, | ||
146 | - marginTop: printOperation!.printInfo.topMargin, | ||
147 | - marginRight: printOperation!.printInfo.rightMargin, | ||
148 | - marginBottom: printOperation!.printInfo.bottomMargin | ||
149 | - ) | 164 | + let window = NSApplication.shared.mainWindow! |
165 | + printOperation!.runModal(for: window, delegate: self, didRun: #selector(printOperationDidRun(printOperation:success:contextInfo:)), contextInfo: nil) | ||
150 | } | 166 | } |
151 | 167 | ||
152 | - func cancelJob(_ error: String?) { | ||
153 | - printing.onCompleted(printJob: self, completed: false, error: error as NSString?) | 168 | + func cancelJob(_: String?) { |
169 | + pdfDocument = nil | ||
170 | + semaphore.signal() | ||
154 | } | 171 | } |
155 | 172 | ||
156 | public static func sharePdf(data: Data, withSourceRect rect: CGRect, andName name: String) { | 173 | public static func sharePdf(data: Data, withSourceRect rect: CGRect, andName name: String) { |
@@ -17,12 +17,29 @@ | @@ -17,12 +17,29 @@ | ||
17 | import FlutterMacOS | 17 | import FlutterMacOS |
18 | import Foundation | 18 | import Foundation |
19 | 19 | ||
20 | +// Dart:ffi API | ||
21 | +private var _printingPlugin: PrintingPlugin? | ||
22 | + | ||
23 | +@_cdecl("net_nfet_printing_set_document") | ||
24 | +func setDocument(job: UInt32, doc: UnsafePointer<UInt8>, size: UInt64) { | ||
25 | + _printingPlugin!.jobs[job]?.setDocument(Data(bytes: doc, count: Int(size))) | ||
26 | +} | ||
27 | + | ||
28 | +@_cdecl("net_nfet_printing_set_error") | ||
29 | +func setError(job: UInt32, message: UnsafePointer<CChar>) { | ||
30 | + _printingPlugin!.jobs[job]?.cancelJob(String(cString: message)) | ||
31 | +} | ||
32 | + | ||
33 | +// End of Dart:ffi API | ||
34 | + | ||
20 | public class PrintingPlugin: NSObject, FlutterPlugin { | 35 | public class PrintingPlugin: NSObject, FlutterPlugin { |
21 | private var channel: FlutterMethodChannel | 36 | private var channel: FlutterMethodChannel |
37 | + public var jobs = [UInt32: PrintJob]() | ||
22 | 38 | ||
23 | init(_ channel: FlutterMethodChannel) { | 39 | init(_ channel: FlutterMethodChannel) { |
24 | self.channel = channel | 40 | self.channel = channel |
25 | super.init() | 41 | super.init() |
42 | + _printingPlugin = self | ||
26 | } | 43 | } |
27 | 44 | ||
28 | /// Entry point | 45 | /// Entry point |
@@ -44,6 +61,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | @@ -44,6 +61,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | ||
44 | let marginRight = CGFloat((args["marginRight"] as? NSNumber)?.floatValue ?? 0.0) | 61 | let marginRight = CGFloat((args["marginRight"] as? NSNumber)?.floatValue ?? 0.0) |
45 | let marginBottom = CGFloat((args["marginBottom"] as? NSNumber)?.floatValue ?? 0.0) | 62 | let marginBottom = CGFloat((args["marginBottom"] as? NSNumber)?.floatValue ?? 0.0) |
46 | let printJob = PrintJob(printing: self, index: args["job"] as! Int) | 63 | let printJob = PrintJob(printing: self, index: args["job"] as! Int) |
64 | + jobs[args["job"] as! UInt32] = printJob | ||
47 | printJob.printPdf(name: name, | 65 | printJob.printPdf(name: name, |
48 | withPageSize: CGSize( | 66 | withPageSize: CGSize( |
49 | width: width, | 67 | width: width, |
@@ -108,13 +126,6 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | @@ -108,13 +126,6 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | ||
108 | andBaseUrl: args["baseUrl"] as? String == nil ? nil : URL(string: args["baseUrl"] as! String) | 126 | andBaseUrl: args["baseUrl"] as? String == nil ? nil : URL(string: args["baseUrl"] as! String) |
109 | ) | 127 | ) |
110 | result(NSNumber(value: 1)) | 128 | result(NSNumber(value: 1)) |
111 | -// } else if call.method == "pickPrinter" { | ||
112 | -// PrintJob.pickPrinter(result: result, withSourceRect: CGRect( | ||
113 | -// x: CGFloat((args["x"] as? NSNumber)?.floatValue ?? 0.0), | ||
114 | -// y: CGFloat((args["y"] as? NSNumber)?.floatValue ?? 0.0), | ||
115 | -// width: CGFloat((args["w"] as? NSNumber)?.floatValue ?? 0.0), | ||
116 | -// height: CGFloat((args["h"] as? NSNumber)?.floatValue ?? 0.0) | ||
117 | -// )) | ||
118 | } else if call.method == "printingInfo" { | 129 | } else if call.method == "printingInfo" { |
119 | result(PrintJob.printingInfo()) | 130 | result(PrintJob.printingInfo()) |
120 | } else if call.method == "rasterPdf" { | 131 | } else if call.method == "rasterPdf" { |
@@ -143,19 +154,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | @@ -143,19 +154,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | ||
143 | "job": printJob.index, | 154 | "job": printJob.index, |
144 | ] as [String: Any] | 155 | ] as [String: Any] |
145 | 156 | ||
146 | - channel.invokeMethod("onLayout", arguments: arg, result: { (result: Any?) -> Void in | ||
147 | - if result as? Bool == false { | ||
148 | - printJob.cancelJob(nil) | ||
149 | - } else if result is FlutterError { | ||
150 | - let error = result as! FlutterError | ||
151 | - printJob.cancelJob(error.message) | ||
152 | - } else if result is FlutterStandardTypedData { | ||
153 | - let object = result as! FlutterStandardTypedData | ||
154 | - printJob.setDocument(object.data) | ||
155 | - } else { | ||
156 | - printJob.cancelJob("Unknown data type") | ||
157 | - } | ||
158 | - }) | 157 | + channel.invokeMethod("onLayout", arguments: arg) |
159 | } | 158 | } |
160 | 159 | ||
161 | /// send completion status to flutter | 160 | /// send completion status to flutter |
@@ -166,6 +165,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | @@ -166,6 +165,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin { | ||
166 | "job": printJob.index, | 165 | "job": printJob.index, |
167 | ] | 166 | ] |
168 | channel.invokeMethod("onCompleted", arguments: data) | 167 | channel.invokeMethod("onCompleted", arguments: data) |
168 | + jobs.removeValue(forKey: UInt32(printJob.index)) | ||
169 | } | 169 | } |
170 | 170 | ||
171 | /// send html to pdf data result to flutter | 171 | /// send html to pdf data result to flutter |
-
Please register or login to post a comment