David PHAM-VAN

Review directPrint internals

@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
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 - Implement dynamic layout on iOS and macOS
  9 +- Review directPrint internals
9 10
10 ## 5.0.0-nullsafety.1 11 ## 5.0.0-nullsafety.1
11 12
@@ -87,32 +87,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -87,32 +87,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
87 printing.onCompleted(printJob: self, completed: completed, error: error?.localizedDescription as NSString?) 87 printing.onCompleted(printJob: self, completed: completed, error: error?.localizedDescription as NSString?)
88 } 88 }
89 89
90 - func directPrintPdf(name: String, data: Data, withPrinter printerID: String) {  
91 - let printing = UIPrintInteractionController.isPrintingAvailable  
92 - if !printing {  
93 - self.printing.onCompleted(printJob: self, completed: false, error: "Printing not available")  
94 - return  
95 - }  
96 -  
97 - let controller = UIPrintInteractionController.shared  
98 -  
99 - let printInfo = UIPrintInfo.printInfo()  
100 - printInfo.jobName = name  
101 - printInfo.outputType = .general  
102 - controller.printInfo = printInfo  
103 - controller.printingItem = data  
104 - let printerURL = URL(string: printerID)  
105 -  
106 - if printerURL == nil {  
107 - self.printing.onCompleted(printJob: self, completed: false, error: "Unable to find printer URL")  
108 - return  
109 - }  
110 -  
111 - let printer = UIPrinter(url: printerURL!)  
112 - controller.print(to: printer, completionHandler: completionHandler)  
113 - }  
114 -  
115 - func printPdf(name: String, withPageSize size: CGSize, andMargin _: CGRect) { 90 + func printPdf(name: String, withPageSize size: CGSize, andMargin _: CGRect, withPrinter printerID: String?) {
116 let printing = UIPrintInteractionController.isPrintingAvailable 91 let printing = UIPrintInteractionController.isPrintingAvailable
117 if !printing { 92 if !printing {
118 self.printing.onCompleted(printJob: self, completed: false, error: "Printing not available") 93 self.printing.onCompleted(printJob: self, completed: false, error: "Printing not available")
@@ -139,6 +114,20 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -139,6 +114,20 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
139 controller.showsPaperSelectionForLoadedPapers = true 114 controller.showsPaperSelectionForLoadedPapers = true
140 115
141 controller.printPageRenderer = self 116 controller.printPageRenderer = self
  117 +
  118 + if printerID != nil {
  119 + let printerURL = URL(string: printerID!)
  120 +
  121 + if printerURL == nil {
  122 + self.printing.onCompleted(printJob: self, completed: false, error: "Unable to find printer URL")
  123 + return
  124 + }
  125 +
  126 + let printer = UIPrinter(url: printerURL!)
  127 + controller.print(to: printer, completionHandler: completionHandler)
  128 + return
  129 + }
  130 +
142 controller.present(animated: true, completionHandler: completionHandler) 131 controller.present(animated: true, completionHandler: completionHandler)
143 } 132 }
144 133
@@ -54,12 +54,13 @@ public class PrintingPlugin: NSObject, FlutterPlugin { @@ -54,12 +54,13 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
54 let args = call.arguments! as! [String: Any] 54 let args = call.arguments! as! [String: Any]
55 if call.method == "printPdf" { 55 if call.method == "printPdf" {
56 let name = args["name"] as! String 56 let name = args["name"] as! String
57 - let width = CGFloat((args["width"] as? NSNumber)?.floatValue ?? 0.0)  
58 - let height = CGFloat((args["height"] as? NSNumber)?.floatValue ?? 0.0)  
59 - let marginLeft = CGFloat((args["marginLeft"] as? NSNumber)?.floatValue ?? 0.0)  
60 - let marginTop = CGFloat((args["marginTop"] as? NSNumber)?.floatValue ?? 0.0)  
61 - let marginRight = CGFloat((args["marginRight"] as? NSNumber)?.floatValue ?? 0.0)  
62 - let marginBottom = CGFloat((args["marginBottom"] as? NSNumber)?.floatValue ?? 0.0) 57 + let printer = args["printer"] as? String
  58 + let width = CGFloat((args["width"] as! NSNumber).floatValue)
  59 + let height = CGFloat((args["height"] as! NSNumber).floatValue)
  60 + let marginLeft = CGFloat((args["marginLeft"] as! NSNumber).floatValue)
  61 + let marginTop = CGFloat((args["marginTop"] as! NSNumber).floatValue)
  62 + let marginRight = CGFloat((args["marginRight"] as! NSNumber).floatValue)
  63 + let marginBottom = CGFloat((args["marginBottom"] as! NSNumber).floatValue)
63 let printJob = PrintJob(printing: self, index: args["job"] as! Int) 64 let printJob = PrintJob(printing: self, index: args["job"] as! Int)
64 jobs[args["job"] as! UInt32] = printJob 65 jobs[args["job"] as! UInt32] = printJob
65 printJob.printPdf(name: name, 66 printJob.printPdf(name: name,
@@ -72,14 +73,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin { @@ -72,14 +73,7 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
72 y: marginTop, 73 y: marginTop,
73 width: width - marginRight - marginLeft, 74 width: width - marginRight - marginLeft,
74 height: height - marginBottom - marginTop 75 height: height - marginBottom - marginTop
75 - ))  
76 - result(NSNumber(value: 1))  
77 - } else if call.method == "directPrintPdf" {  
78 - let name = args["name"] as! String  
79 - let printer = args["printer"] as! String  
80 - let object = args["doc"] as! FlutterStandardTypedData  
81 - let printJob = PrintJob(printing: self, index: args["job"] as! Int)  
82 - printJob.directPrintPdf(name: name, data: object.data, withPrinter: printer) 76 + ), withPrinter: printer)
83 result(NSNumber(value: 1)) 77 result(NSNumber(value: 1))
84 } else if call.method == "sharePdf" { 78 } else if call.method == "sharePdf" {
85 let object = args["doc"] as! FlutterStandardTypedData 79 let object = args["doc"] as! FlutterStandardTypedData
@@ -207,14 +207,12 @@ class MethodChannelPrinting extends PrintingPlatform { @@ -207,14 +207,12 @@ class MethodChannelPrinting extends PrintingPlatform {
207 ) async { 207 ) async {
208 final job = _printJobs.add( 208 final job = _printJobs.add(
209 onCompleted: Completer<bool>(), 209 onCompleted: Completer<bool>(),
  210 + onLayout: onLayout,
210 ); 211 );
211 212
212 - final bytes = await onLayout(format);  
213 -  
214 final params = <String, dynamic>{ 213 final params = <String, dynamic>{
215 'name': name, 214 'name': name,
216 'printer': printer.url, 215 'printer': printer.url,
217 - 'doc': bytes,  
218 'width': format.width, 216 'width': format.width,
219 'height': format.height, 217 'height': format.height,
220 'marginLeft': format.marginLeft, 218 'marginLeft': format.marginLeft,
@@ -223,10 +221,12 @@ class MethodChannelPrinting extends PrintingPlatform { @@ -223,10 +221,12 @@ class MethodChannelPrinting extends PrintingPlatform {
223 'marginBottom': format.marginBottom, 221 'marginBottom': format.marginBottom,
224 'job': job.index, 222 'job': job.index,
225 }; 223 };
226 - await _channel.invokeMethod<int>('directPrintPdf', params);  
227 - final result = await job.onCompleted!.future;  
228 - _printJobs.remove(job.index);  
229 - return result; 224 + await _channel.invokeMethod<int>('printPdf', params);
  225 + try {
  226 + return await job.onCompleted!.future;
  227 + } finally {
  228 + _printJobs.remove(job.index);
  229 + }
230 } 230 }
231 231
232 @override 232 @override
@@ -166,7 +166,7 @@ class PrintingPlugin extends PrintingPlatform { @@ -166,7 +166,7 @@ class PrintingPlugin extends PrintingPlatform {
166 String name, 166 String name,
167 PdfPageFormat format, 167 PdfPageFormat format,
168 ) { 168 ) {
169 - throw UnimplementedError(); 169 + return layoutPdf(onLayout, name, format);
170 } 170 }
171 171
172 @override 172 @override
@@ -109,64 +109,85 @@ static void job_completed(GtkPrintJob* gtk_print_job, @@ -109,64 +109,85 @@ static void job_completed(GtkPrintJob* gtk_print_job,
109 } 109 }
110 110
111 bool print_job::print_pdf(const gchar* name, 111 bool print_job::print_pdf(const gchar* name,
  112 + const gchar* printer,
112 double pageWidth, 113 double pageWidth,
113 double pageHeight, 114 double pageHeight,
114 double marginLeft, 115 double marginLeft,
115 double marginTop, 116 double marginTop,
116 double marginRight, 117 double marginRight,
117 double marginBottom) { 118 double marginBottom) {
118 - documentName = strdup(name);  
119 - auto dialog =  
120 - GTK_PRINT_UNIX_DIALOG(gtk_print_unix_dialog_new(documentName, nullptr));  
121 - gtk_print_unix_dialog_set_manual_capabilities(  
122 - dialog, (GtkPrintCapabilities)(GTK_PRINT_CAPABILITY_GENERATE_PDF));  
123 -  
124 - gtk_widget_realize(GTK_WIDGET(dialog));  
125 -  
126 - auto response = gtk_dialog_run(GTK_DIALOG(dialog));  
127 - gtk_widget_hide(GTK_WIDGET(dialog));  
128 -  
129 - switch (response) {  
130 - case GTK_RESPONSE_OK: {  
131 - GtkPrinter* printer = gtk_print_unix_dialog_get_selected_printer(  
132 - GTK_PRINT_UNIX_DIALOG(dialog));  
133 - if (!gtk_printer_accepts_pdf(printer)) {  
134 - on_completed(this, false, "This printer does not accept PDF jobs");  
135 - break;  
136 - } 119 + GtkPrintSettings* settings;
  120 + GtkPageSetup* setup;
  121 +
  122 + if (printer != nullptr) {
  123 + _printer = nullptr;
  124 + auto pname = strdup(printer);
  125 + gtk_enumerate_printers(search_printer, pname, nullptr, true);
  126 + free(pname);
  127 +
  128 + if (!_printer) {
  129 + on_completed(this, false, "Printer not found");
  130 + return false;
  131 + }
137 132
138 - GtkPrintSettings* settings =  
139 - gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog));  
140 - GtkPageSetup* setup =  
141 - gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dialog)); 133 + settings = gtk_print_settings_new();
  134 + setup = gtk_page_setup_new();
  135 +
  136 + } else {
  137 + auto dialog =
  138 + GTK_PRINT_UNIX_DIALOG(gtk_print_unix_dialog_new(name, nullptr));
  139 + gtk_print_unix_dialog_set_manual_capabilities(
  140 + dialog, (GtkPrintCapabilities)(GTK_PRINT_CAPABILITY_GENERATE_PDF));
  141 +
  142 + gtk_widget_realize(GTK_WIDGET(dialog));
  143 +
  144 + auto response = gtk_dialog_run(GTK_DIALOG(dialog));
  145 + gtk_widget_hide(GTK_WIDGET(dialog));
  146 +
  147 + switch (response) {
  148 + case GTK_RESPONSE_OK: {
  149 + _printer = gtk_print_unix_dialog_get_selected_printer(
  150 + GTK_PRINT_UNIX_DIALOG(dialog));
  151 + settings =
  152 + gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog));
  153 + setup =
  154 + gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dialog));
  155 + gtk_widget_destroy(GTK_WIDGET(dialog));
  156 + } break;
  157 + case GTK_RESPONSE_DELETE_EVENT: // Fall through.
  158 + case GTK_RESPONSE_CANCEL: // Cancel
  159 + case GTK_RESPONSE_APPLY: // Preview
  160 + default:
  161 + gtk_widget_destroy(GTK_WIDGET(dialog));
  162 + on_completed(this, false, nullptr);
  163 + return true;
  164 + }
  165 + }
142 166
143 - auto width = gtk_page_setup_get_page_width(setup, GTK_UNIT_POINTS);  
144 - auto height = gtk_page_setup_get_page_height(setup, GTK_UNIT_POINTS);  
145 - auto marginLeft = gtk_page_setup_get_left_margin(setup, GTK_UNIT_POINTS);  
146 - auto marginTop = gtk_page_setup_get_top_margin(setup, GTK_UNIT_POINTS);  
147 - auto marginRight =  
148 - gtk_page_setup_get_right_margin(setup, GTK_UNIT_POINTS);  
149 - auto marginBottom =  
150 - gtk_page_setup_get_bottom_margin(setup, GTK_UNIT_POINTS); 167 + if (!gtk_printer_accepts_pdf(_printer)) {
  168 + on_completed(this, false, "This printer does not accept PDF jobs");
  169 + g_object_unref(_printer);
  170 + g_object_unref(settings);
  171 + g_object_unref(setup);
  172 + return false;
  173 + }
151 174
152 - printJob = gtk_print_job_new(name, printer, settings, setup); 175 + auto _width = gtk_page_setup_get_page_width(setup, GTK_UNIT_POINTS);
  176 + auto _height = gtk_page_setup_get_page_height(setup, GTK_UNIT_POINTS);
  177 + auto _marginLeft = gtk_page_setup_get_left_margin(setup, GTK_UNIT_POINTS);
  178 + auto _marginTop = gtk_page_setup_get_top_margin(setup, GTK_UNIT_POINTS);
  179 + auto _marginRight = gtk_page_setup_get_right_margin(setup, GTK_UNIT_POINTS);
  180 + auto _marginBottom = gtk_page_setup_get_bottom_margin(setup, GTK_UNIT_POINTS);
153 181
154 - on_layout(this, width, height, marginLeft, marginTop, marginRight,  
155 - marginBottom); 182 + printJob = gtk_print_job_new(name, _printer, settings, setup);
156 183
157 - g_object_unref(settings);  
158 - gtk_widget_destroy(GTK_WIDGET(dialog)); 184 + on_layout(this, _width, _height, _marginLeft, _marginTop, _marginRight,
  185 + _marginBottom);
159 186
160 - return true;  
161 - }  
162 - case GTK_RESPONSE_DELETE_EVENT: // Fall through.  
163 - case GTK_RESPONSE_CANCEL: // Cancel  
164 - case GTK_RESPONSE_APPLY: // Preview  
165 - break;  
166 - } 187 + g_object_unref(_printer);
  188 + g_object_unref(settings);
  189 + g_object_unref(setup);
167 190
168 - gtk_widget_destroy(GTK_WIDGET(dialog));  
169 - on_completed(this, false, nullptr);  
170 return true; 191 return true;
171 } 192 }
172 193
@@ -24,7 +24,6 @@ @@ -24,7 +24,6 @@
24 class print_job { 24 class print_job {
25 private: 25 private:
26 const int index; 26 const int index;
27 - char* documentName = nullptr;  
28 GtkPrintJob* printJob; 27 GtkPrintJob* printJob;
29 28
30 public: 29 public:
@@ -42,6 +41,7 @@ class print_job { @@ -42,6 +41,7 @@ class print_job {
42 const gchar* printer); 41 const gchar* printer);
43 42
44 bool print_pdf(const gchar* name, 43 bool print_pdf(const gchar* name,
  44 + const gchar* printer,
45 double pageWidth, 45 double pageWidth,
46 double pageHeight, 46 double pageHeight,
47 double marginLeft, 47 double marginLeft,
@@ -53,6 +53,9 @@ static void printing_plugin_handle_method_call(PrintingPlugin* self, @@ -53,6 +53,9 @@ static void printing_plugin_handle_method_call(PrintingPlugin* self,
53 53
54 } else if (strcmp(method, "printPdf") == 0) { 54 } else if (strcmp(method, "printPdf") == 0) {
55 auto name = fl_value_get_string(fl_value_lookup_string(args, "name")); 55 auto name = fl_value_get_string(fl_value_lookup_string(args, "name"));
  56 + auto printerValue = fl_value_lookup_string(args, "printer");
  57 + auto printer =
  58 + printerValue == nullptr ? nullptr : fl_value_get_string(printerValue);
56 auto jobNum = fl_value_get_int(fl_value_lookup_string(args, "job")); 59 auto jobNum = fl_value_get_int(fl_value_lookup_string(args, "job"));
57 auto pageWidth = fl_value_get_float(fl_value_lookup_string(args, "width")); 60 auto pageWidth = fl_value_get_float(fl_value_lookup_string(args, "width"));
58 auto pageHeight = 61 auto pageHeight =
@@ -67,7 +70,7 @@ static void printing_plugin_handle_method_call(PrintingPlugin* self, @@ -67,7 +70,7 @@ static void printing_plugin_handle_method_call(PrintingPlugin* self,
67 fl_value_get_float(fl_value_lookup_string(args, "marginBottom")); 70 fl_value_get_float(fl_value_lookup_string(args, "marginBottom"));
68 71
69 auto job = new print_job(jobNum); 72 auto job = new print_job(jobNum);
70 - auto res = job->print_pdf(name, pageWidth, pageHeight, marginLeft, 73 + auto res = job->print_pdf(name, printer, pageWidth, pageHeight, marginLeft,
71 marginTop, marginRight, marginBottom); 74 marginTop, marginRight, marginBottom);
72 if (!res) { 75 if (!res) {
73 delete job; 76 delete job;
@@ -75,18 +78,6 @@ static void printing_plugin_handle_method_call(PrintingPlugin* self, @@ -75,18 +78,6 @@ static void printing_plugin_handle_method_call(PrintingPlugin* self,
75 g_autoptr(FlValue) result = fl_value_new_int(res); 78 g_autoptr(FlValue) result = fl_value_new_int(res);
76 response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); 79 response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
77 80
78 - } else if (strcmp(method, "directPrintPdf") == 0) {  
79 - auto jobNum = fl_value_get_int(fl_value_lookup_string(args, "job"));  
80 - auto name = fl_value_get_string(fl_value_lookup_string(args, "name"));  
81 - auto printer = fl_value_get_string(fl_value_lookup_string(args, "printer"));  
82 - auto doc = fl_value_get_uint8_list(fl_value_lookup_string(args, "doc"));  
83 - auto size = fl_value_get_length(fl_value_lookup_string(args, "doc"));  
84 -  
85 - auto job = std::make_unique<print_job>(jobNum);  
86 - auto res = job->direct_print_pdf(name, doc, size, printer);  
87 - g_autoptr(FlValue) result = fl_value_new_int(res);  
88 - response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));  
89 -  
90 } else if (strcmp(method, "sharePdf") == 0) { 81 } else if (strcmp(method, "sharePdf") == 0) {
91 auto name = fl_value_get_string(fl_value_lookup_string(args, "name")); 82 auto name = fl_value_get_string(fl_value_lookup_string(args, "name"));
92 auto doc = fl_value_get_uint8_list(fl_value_lookup_string(args, "doc")); 83 auto doc = fl_value_get_uint8_list(fl_value_lookup_string(args, "doc"));
@@ -234,4 +225,4 @@ void on_completed(print_job* job, bool completed, const char* error) { @@ -234,4 +225,4 @@ void on_completed(print_job* job, bool completed, const char* error) {
234 225
235 fl_method_channel_invoke_method(channel, "onCompleted", map, nullptr, nullptr, 226 fl_method_channel_invoke_method(channel, "onCompleted", map, nullptr, nullptr,
236 nullptr); 227 nullptr);
237 -}  
  228 +}
@@ -119,33 +119,7 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { @@ -119,33 +119,7 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
119 return printers 119 return printers
120 } 120 }
121 121
122 - public func directPrintPdf(name: String, data: Data, withPrinter printer: String, width: CGFloat, height: CGFloat) {  
123 - let sharedInfo = NSPrintInfo.shared  
124 - let sharedDict = sharedInfo.dictionary()  
125 - let printInfoDict = NSMutableDictionary(dictionary: sharedDict)  
126 - let printInfo = NSPrintInfo(dictionary: printInfoDict as! [NSPrintInfo.AttributeKey: Any])  
127 - printInfo.printer = NSPrinter(name: printer)!  
128 -  
129 - let bytesPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count)  
130 - data.copyBytes(to: bytesPointer, count: data.count)  
131 - let dataProvider = CGDataProvider(dataInfo: nil, data: bytesPointer, size: data.count, releaseData: dataProviderReleaseDataCallback)  
132 - pdfDocument = CGPDFDocument(dataProvider!)  
133 - printInfo.paperSize = NSSize(width: width, height: height)  
134 - if width > height {  
135 - printInfo.orientation = NSPrintInfo.PaperOrientation.landscape  
136 - }  
137 -  
138 - // Print the custom view  
139 - printOperation = NSPrintOperation(view: self, printInfo: printInfo)  
140 - printOperation!.jobTitle = name  
141 - printOperation!.showsPrintPanel = false  
142 - printOperation!.showsProgressPanel = false  
143 -  
144 - let window = NSApplication.shared.mainWindow!  
145 - printOperation!.runModal(for: window, delegate: self, didRun: #selector(printOperationDidRun(printOperation:success:contextInfo:)), contextInfo: nil)  
146 - }  
147 -  
148 - public func printPdf(name: String, withPageSize size: CGSize, andMargin _: CGRect) { 122 + public func printPdf(name: String, withPageSize size: CGSize, andMargin _: CGRect, withPrinter printer: String?) {
149 let sharedInfo = NSPrintInfo.shared 123 let sharedInfo = NSPrintInfo.shared
150 let sharedDict = sharedInfo.dictionary() 124 let sharedDict = sharedInfo.dictionary()
151 let printInfoDict = NSMutableDictionary(dictionary: sharedDict) 125 let printInfoDict = NSMutableDictionary(dictionary: sharedDict)
@@ -160,6 +134,11 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { @@ -160,6 +134,11 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
160 printOperation = NSPrintOperation(view: self, printInfo: printInfo) 134 printOperation = NSPrintOperation(view: self, printInfo: printInfo)
161 printOperation!.jobTitle = name 135 printOperation!.jobTitle = name
162 printOperation!.printPanel.options = [.showsPreview, .showsPaperSize, .showsOrientation] 136 printOperation!.printPanel.options = [.showsPreview, .showsPaperSize, .showsOrientation]
  137 + if printer != nil {
  138 + printInfo.printer = NSPrinter(name: printer!)!
  139 + printOperation!.showsPrintPanel = false
  140 + printOperation!.showsProgressPanel = false
  141 + }
163 142
164 let window = NSApplication.shared.mainWindow! 143 let window = NSApplication.shared.mainWindow!
165 printOperation!.runModal(for: window, delegate: self, didRun: #selector(printOperationDidRun(printOperation:success:contextInfo:)), contextInfo: nil) 144 printOperation!.runModal(for: window, delegate: self, didRun: #selector(printOperationDidRun(printOperation:success:contextInfo:)), contextInfo: nil)
@@ -54,12 +54,13 @@ public class PrintingPlugin: NSObject, FlutterPlugin { @@ -54,12 +54,13 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
54 let args = call.arguments! as! [String: Any] 54 let args = call.arguments! as! [String: Any]
55 if call.method == "printPdf" { 55 if call.method == "printPdf" {
56 let name = args["name"] as! String 56 let name = args["name"] as! String
57 - let width = CGFloat((args["width"] as? NSNumber)?.floatValue ?? 0.0)  
58 - let height = CGFloat((args["height"] as? NSNumber)?.floatValue ?? 0.0)  
59 - let marginLeft = CGFloat((args["marginLeft"] as? NSNumber)?.floatValue ?? 0.0)  
60 - let marginTop = CGFloat((args["marginTop"] as? NSNumber)?.floatValue ?? 0.0)  
61 - let marginRight = CGFloat((args["marginRight"] as? NSNumber)?.floatValue ?? 0.0)  
62 - let marginBottom = CGFloat((args["marginBottom"] as? NSNumber)?.floatValue ?? 0.0) 57 + let printer = args["printer"] as? String
  58 + let width = CGFloat((args["width"] as! NSNumber).floatValue)
  59 + let height = CGFloat((args["height"] as! NSNumber).floatValue)
  60 + let marginLeft = CGFloat((args["marginLeft"] as! NSNumber).floatValue)
  61 + let marginTop = CGFloat((args["marginTop"] as! NSNumber).floatValue)
  62 + let marginRight = CGFloat((args["marginRight"] as! NSNumber).floatValue)
  63 + let marginBottom = CGFloat((args["marginBottom"] as! NSNumber).floatValue)
63 let printJob = PrintJob(printing: self, index: args["job"] as! Int) 64 let printJob = PrintJob(printing: self, index: args["job"] as! Int)
64 jobs[args["job"] as! UInt32] = printJob 65 jobs[args["job"] as! UInt32] = printJob
65 printJob.printPdf(name: name, 66 printJob.printPdf(name: name,
@@ -72,21 +73,12 @@ public class PrintingPlugin: NSObject, FlutterPlugin { @@ -72,21 +73,12 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
72 y: marginTop, 73 y: marginTop,
73 width: width - marginRight - marginLeft, 74 width: width - marginRight - marginLeft,
74 height: height - marginBottom - marginTop 75 height: height - marginBottom - marginTop
75 - )) 76 + ), withPrinter: printer)
76 result(NSNumber(value: 1)) 77 result(NSNumber(value: 1))
77 } else if call.method == "listPrinters" { 78 } else if call.method == "listPrinters" {
78 let printJob = PrintJob(printing: self, index: -1) 79 let printJob = PrintJob(printing: self, index: -1)
79 let r = printJob.listPrinters() 80 let r = printJob.listPrinters()
80 result(r) 81 result(r)
81 - } else if call.method == "directPrintPdf" {  
82 - let name = args["name"] as! String  
83 - let printer = args["printer"] as! String  
84 - let object = args["doc"] as! FlutterStandardTypedData  
85 - let width = CGFloat((args["width"] as? NSNumber)?.floatValue ?? 0.0)  
86 - let height = CGFloat((args["height"] as? NSNumber)?.floatValue ?? 0.0)  
87 - let printJob = PrintJob(printing: self, index: args["job"] as! Int)  
88 - printJob.directPrintPdf(name: name, data: object.data, withPrinter: printer, width: width, height: height)  
89 - result(NSNumber(1))  
90 } else if call.method == "sharePdf" { 82 } else if call.method == "sharePdf" {
91 let object = args["doc"] as! FlutterStandardTypedData 83 let object = args["doc"] as! FlutterStandardTypedData
92 PrintJob.sharePdf( 84 PrintJob.sharePdf(
@@ -73,119 +73,70 @@ std::wstring fromUtf8(std::string str) { @@ -73,119 +73,70 @@ std::wstring fromUtf8(std::string str) {
73 PrintJob::PrintJob(Printing* printing, int index) 73 PrintJob::PrintJob(Printing* printing, int index)
74 : printing(printing), index(index) {} 74 : printing(printing), index(index) {}
75 75
76 -bool PrintJob::directPrintPdf(std::string name,  
77 - std::vector<uint8_t> data,  
78 - std::string withPrinter) {  
79 - FPDF_InitLibraryWithConfig(nullptr);  
80 -  
81 - auto doc = FPDF_LoadMemDocument64(data.data(), data.size(), nullptr);  
82 - if (!doc) {  
83 - FPDF_DestroyLibrary();  
84 - return false;  
85 - }  
86 -  
87 - hDC = CreateDC(TEXT("WINSPOOL"), fromUtf8(withPrinter).c_str(), NULL, NULL);  
88 - if (!hDC) {  
89 - FPDF_CloseDocument(doc);  
90 - FPDF_DestroyLibrary();  
91 - return false;  
92 - }  
93 -  
94 - DOCINFO docInfo;  
95 - ZeroMemory(&docInfo, sizeof(docInfo));  
96 - docInfo.cbSize = sizeof(DOCINFO);  
97 - auto docName = fromUtf8(name);  
98 - docInfo.lpszDocName = docName.c_str();  
99 - StartDoc(hDC, &docInfo);  
100 -  
101 - int pageCount = FPDF_GetPageCount(doc);  
102 -  
103 - for (auto i = 0; i < pageCount; i++) {  
104 - StartPage(hDC);  
105 - auto page = FPDF_LoadPage(doc, i);  
106 - if (!page) {  
107 - EndDoc(hDC);  
108 - DeleteDC(hDC);  
109 - FPDF_CloseDocument(doc);  
110 - FPDF_DestroyLibrary(); 76 +bool PrintJob::printPdf(std::string name, std::string printer) {
  77 + documentName = name;
  78 +
  79 + if (printer.empty()) {
  80 + PRINTDLG pd;
  81 + DEVMODE* dm = static_cast<DEVMODE*>(GlobalAlloc(0, sizeof(DEVMODE)));
  82 + ZeroMemory(dm, sizeof(DEVMODE));
  83 + dm->dmFields = DM_ORIENTATION;
  84 + dm->dmOrientation = 2;
  85 +
  86 + // Initialize PRINTDLG
  87 + ZeroMemory(&pd, sizeof(pd));
  88 + pd.lStructSize = sizeof(pd);
  89 +
  90 + // Initialize PRINTDLG
  91 + pd.hwndOwner = nullptr;
  92 + pd.hDevMode = dm;
  93 + pd.hDevNames = nullptr; // Don't forget to free or store hDevNames.
  94 + pd.hDC = nullptr;
  95 + pd.Flags = PD_USEDEVMODECOPIES | PD_RETURNDC | PD_PRINTSETUP |
  96 + PD_NOSELECTION | PD_NOPAGENUMS;
  97 + pd.nCopies = 1;
  98 + pd.nFromPage = 0xFFFF;
  99 + pd.nToPage = 0xFFFF;
  100 + pd.nMinPage = 1;
  101 + pd.nMaxPage = 0xFFFF;
  102 +
  103 + auto r = PrintDlg(&pd);
  104 +
  105 + if (r == 1) {
  106 + hDC = pd.hDC;
  107 + hDevMode = pd.hDevMode;
  108 + hDevNames = pd.hDevNames;
  109 + }
  110 + } else {
  111 + hDC = CreateDC(TEXT("WINSPOOL"), fromUtf8(printer).c_str(), NULL, NULL);
  112 + if (!hDC) {
111 return false; 113 return false;
112 } 114 }
113 - auto pageWidth = FPDF_GetPageWidth(page);  
114 - auto pageHeight = FPDF_GetPageHeight(page);  
115 - auto dpiX = GetDeviceCaps(hDC, LOGPIXELSX);  
116 - auto dpiY = GetDeviceCaps(hDC, LOGPIXELSY);  
117 - auto width = static_cast<int>(pageWidth / pdfDpi * dpiX);  
118 - auto height = static_cast<int>(pageHeight / pdfDpi * dpiY);  
119 - FPDF_RenderPage(hDC, page, 0, 0, width, height, 0, FPDF_ANNOT);  
120 - FPDF_ClosePage(page);  
121 - EndPage(hDC); 115 + hDevMode = nullptr;
  116 + hDevNames = nullptr;
122 } 117 }
123 118
124 - EndDoc(hDC);  
125 - DeleteDC(hDC);  
126 - FPDF_CloseDocument(doc);  
127 - FPDF_DestroyLibrary(); 119 + auto dpiX = static_cast<double>(GetDeviceCaps(hDC, LOGPIXELSX)) / pdfDpi;
  120 + auto dpiY = static_cast<double>(GetDeviceCaps(hDC, LOGPIXELSY)) / pdfDpi;
  121 + auto pageWidth =
  122 + static_cast<double>(GetDeviceCaps(hDC, PHYSICALWIDTH)) / dpiX;
  123 + auto pageHeight =
  124 + static_cast<double>(GetDeviceCaps(hDC, PHYSICALHEIGHT)) / dpiY;
  125 + auto printableWidth = static_cast<double>(GetDeviceCaps(hDC, HORZRES)) / dpiX;
  126 + auto printableHeight =
  127 + static_cast<double>(GetDeviceCaps(hDC, VERTRES)) / dpiY;
  128 + auto marginLeft =
  129 + static_cast<double>(GetDeviceCaps(hDC, PHYSICALOFFSETX)) / dpiX;
  130 + auto marginTop =
  131 + static_cast<double>(GetDeviceCaps(hDC, PHYSICALOFFSETY)) / dpiY;
  132 + auto marginRight = pageWidth - printableWidth - marginLeft;
  133 + auto marginBottom = pageHeight - printableHeight - marginTop;
  134 +
  135 + printing->onLayout(this, pageWidth, pageHeight, marginLeft, marginTop,
  136 + marginRight, marginBottom);
128 return true; 137 return true;
129 } 138 }
130 139
131 -bool PrintJob::printPdf(std::string name) {  
132 - PRINTDLG pd;  
133 - DEVMODE* dm = static_cast<DEVMODE*>(GlobalAlloc(0, sizeof(DEVMODE)));  
134 - ZeroMemory(dm, sizeof(DEVMODE));  
135 - dm->dmFields = DM_ORIENTATION;  
136 - dm->dmOrientation = 2;  
137 - printf("Printing ... \n");  
138 -  
139 - // Initialize PRINTDLG  
140 - ZeroMemory(&pd, sizeof(pd));  
141 - pd.lStructSize = sizeof(pd);  
142 -  
143 - // Initialize PRINTDLG  
144 - pd.hwndOwner = nullptr;  
145 - pd.hDevMode = dm;  
146 - pd.hDevNames = nullptr; // Don't forget to free or store hDevNames.  
147 - pd.hDC = nullptr;  
148 - pd.Flags = PD_USEDEVMODECOPIES | PD_RETURNDC | PD_PRINTSETUP |  
149 - PD_NOSELECTION | PD_NOPAGENUMS;  
150 - pd.nCopies = 1;  
151 - pd.nFromPage = 0xFFFF;  
152 - pd.nToPage = 0xFFFF;  
153 - pd.nMinPage = 1;  
154 - pd.nMaxPage = 0xFFFF;  
155 -  
156 - auto r = PrintDlg(&pd);  
157 -  
158 - if (r == 1) {  
159 - auto dpiX = static_cast<double>(GetDeviceCaps(pd.hDC, LOGPIXELSX)) / pdfDpi;  
160 - auto dpiY = static_cast<double>(GetDeviceCaps(pd.hDC, LOGPIXELSY)) / pdfDpi;  
161 - auto pageWidth =  
162 - static_cast<double>(GetDeviceCaps(pd.hDC, PHYSICALWIDTH)) / dpiX;  
163 - auto pageHeight =  
164 - static_cast<double>(GetDeviceCaps(pd.hDC, PHYSICALHEIGHT)) / dpiY;  
165 - auto printableWidth =  
166 - static_cast<double>(GetDeviceCaps(pd.hDC, HORZRES)) / dpiX;  
167 - auto printableHeight =  
168 - static_cast<double>(GetDeviceCaps(pd.hDC, VERTRES)) / dpiY;  
169 - auto marginLeft =  
170 - static_cast<double>(GetDeviceCaps(pd.hDC, PHYSICALOFFSETX)) / dpiX;  
171 - auto marginTop =  
172 - static_cast<double>(GetDeviceCaps(pd.hDC, PHYSICALOFFSETY)) / dpiY;  
173 - auto marginRight = pageWidth - printableWidth - marginLeft;  
174 - auto marginBottom = pageHeight - printableHeight - marginTop;  
175 -  
176 - hDC = pd.hDC;  
177 - hDevMode = pd.hDevMode;  
178 - hDevNames = pd.hDevNames;  
179 - documentName = name;  
180 -  
181 - printing->onLayout(this, pageWidth, pageHeight, marginLeft, marginTop,  
182 - marginRight, marginBottom);  
183 - return true;  
184 - }  
185 -  
186 - return false;  
187 -}  
188 -  
189 std::vector<Printer> PrintJob::listPrinters() { 140 std::vector<Printer> PrintJob::listPrinters() {
190 LPTSTR defaultPrinter; 141 LPTSTR defaultPrinter;
191 DWORD size = 0; 142 DWORD size = 0;
@@ -71,11 +71,7 @@ class PrintJob { @@ -71,11 +71,7 @@ class PrintJob {
71 71
72 std::vector<Printer> listPrinters(); 72 std::vector<Printer> listPrinters();
73 73
74 - bool directPrintPdf(std::string name,  
75 - std::vector<uint8_t> data,  
76 - std::string printer);  
77 -  
78 - bool printPdf(std::string name); 74 + bool printPdf(std::string name, std::string printer);
79 75
80 void writeJob(std::vector<uint8_t> data); 76 void writeJob(std::vector<uint8_t> data);
81 77
@@ -70,35 +70,18 @@ class PrintingPlugin : public flutter::Plugin { @@ -70,35 +70,18 @@ class PrintingPlugin : public flutter::Plugin {
70 auto name = vName != arguments->end() && !vName->second.IsNull() 70 auto name = vName != arguments->end() && !vName->second.IsNull()
71 ? std::get<std::string>(vName->second) 71 ? std::get<std::string>(vName->second)
72 : std::string{"document"}; 72 : std::string{"document"};
  73 + auto vPrinter = arguments->find(flutter::EncodableValue("printer"));
  74 + auto printer = vPrinter != arguments->end()
  75 + ? std::get<std::string>(vPrinter->second)
  76 + : std::string{};
73 auto vJob = arguments->find(flutter::EncodableValue("job")); 77 auto vJob = arguments->find(flutter::EncodableValue("job"));
74 auto jobNum = vJob != arguments->end() ? std::get<int>(vJob->second) : -1; 78 auto jobNum = vJob != arguments->end() ? std::get<int>(vJob->second) : -1;
75 auto job = new PrintJob{&printing, jobNum}; 79 auto job = new PrintJob{&printing, jobNum};
76 - auto res = job->printPdf(name); 80 + auto res = job->printPdf(name, printer);
77 if (!res) { 81 if (!res) {
78 delete job; 82 delete job;
79 } 83 }
80 result->Success(flutter::EncodableValue(res ? 1 : 0)); 84 result->Success(flutter::EncodableValue(res ? 1 : 0));
81 - } else if (method_call.method_name().compare("directPrintPdf") == 0) {  
82 - const auto* arguments =  
83 - std::get_if<flutter::EncodableMap>(method_call.arguments());  
84 - auto vName = arguments->find(flutter::EncodableValue("name"));  
85 - auto name = vName != arguments->end() && !vName->second.IsNull()  
86 - ? std::get<std::string>(vName->second)  
87 - : std::string{"document"};  
88 - auto vDoc = arguments->find(flutter::EncodableValue("doc"));  
89 - auto doc = vDoc != arguments->end()  
90 - ? std::get<std::vector<uint8_t>>(vDoc->second)  
91 - : std::vector<uint8_t>{};  
92 - auto vPrinter = arguments->find(flutter::EncodableValue("printer"));  
93 - auto printer = vPrinter != arguments->end()  
94 - ? std::get<std::string>(vPrinter->second)  
95 - : std::string{};  
96 - auto vJob = arguments->find(flutter::EncodableValue("job"));  
97 - auto jobNum = vJob != arguments->end() ? std::get<int>(vJob->second) : -1;  
98 - auto job = std::make_unique<PrintJob>(&printing, jobNum);  
99 - auto res = job->directPrintPdf(name, doc, printer);  
100 - result->Success(flutter::EncodableValue(1));  
101 - printing.onCompleted(job.get(), res, "");  
102 } else if (method_call.method_name().compare("sharePdf") == 0) { 85 } else if (method_call.method_name().compare("sharePdf") == 0) {
103 const auto* arguments = 86 const auto* arguments =
104 std::get_if<flutter::EncodableMap>(method_call.arguments()); 87 std::get_if<flutter::EncodableMap>(method_call.arguments());