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; 224 + await _channel.invokeMethod<int>('printPdf', params);
  225 + try {
  226 + return await job.onCompleted!.future;
  227 + } finally {
228 _printJobs.remove(job.index); 228 _printJobs.remove(job.index);
229 - return result; 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,15 +109,33 @@ static void job_completed(GtkPrintJob* gtk_print_job, @@ -109,15 +109,33 @@ 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 + 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 + }
  132 +
  133 + settings = gtk_print_settings_new();
  134 + setup = gtk_page_setup_new();
  135 +
  136 + } else {
119 auto dialog = 137 auto dialog =
120 - GTK_PRINT_UNIX_DIALOG(gtk_print_unix_dialog_new(documentName, nullptr)); 138 + GTK_PRINT_UNIX_DIALOG(gtk_print_unix_dialog_new(name, nullptr));
121 gtk_print_unix_dialog_set_manual_capabilities( 139 gtk_print_unix_dialog_set_manual_capabilities(
122 dialog, (GtkPrintCapabilities)(GTK_PRINT_CAPABILITY_GENERATE_PDF)); 140 dialog, (GtkPrintCapabilities)(GTK_PRINT_CAPABILITY_GENERATE_PDF));
123 141
@@ -128,46 +146,49 @@ bool print_job::print_pdf(const gchar* name, @@ -128,46 +146,49 @@ bool print_job::print_pdf(const gchar* name,
128 146
129 switch (response) { 147 switch (response) {
130 case GTK_RESPONSE_OK: { 148 case GTK_RESPONSE_OK: {
131 - GtkPrinter* printer = gtk_print_unix_dialog_get_selected_printer( 149 + _printer = gtk_print_unix_dialog_get_selected_printer(
132 GTK_PRINT_UNIX_DIALOG(dialog)); 150 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 - }  
137 -  
138 - GtkPrintSettings* settings = 151 + settings =
139 gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog)); 152 gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog));
140 - GtkPageSetup* setup = 153 + setup =
141 gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dialog)); 154 gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dialog));
142 -  
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);  
151 -  
152 - printJob = gtk_print_job_new(name, printer, settings, setup);  
153 -  
154 - on_layout(this, width, height, marginLeft, marginTop, marginRight,  
155 - marginBottom);  
156 -  
157 - g_object_unref(settings);  
158 gtk_widget_destroy(GTK_WIDGET(dialog)); 155 gtk_widget_destroy(GTK_WIDGET(dialog));
159 -  
160 - return true;  
161 - } 156 + } break;
162 case GTK_RESPONSE_DELETE_EVENT: // Fall through. 157 case GTK_RESPONSE_DELETE_EVENT: // Fall through.
163 case GTK_RESPONSE_CANCEL: // Cancel 158 case GTK_RESPONSE_CANCEL: // Cancel
164 case GTK_RESPONSE_APPLY: // Preview 159 case GTK_RESPONSE_APPLY: // Preview
165 - break;  
166 - }  
167 - 160 + default:
168 gtk_widget_destroy(GTK_WIDGET(dialog)); 161 gtk_widget_destroy(GTK_WIDGET(dialog));
169 on_completed(this, false, nullptr); 162 on_completed(this, false, nullptr);
170 return true; 163 return true;
  164 + }
  165 + }
  166 +
  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 + }
  174 +
  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);
  181 +
  182 + printJob = gtk_print_job_new(name, _printer, settings, setup);
  183 +
  184 + on_layout(this, _width, _height, _marginLeft, _marginTop, _marginRight,
  185 + _marginBottom);
  186 +
  187 + g_object_unref(_printer);
  188 + g_object_unref(settings);
  189 + g_object_unref(setup);
  190 +
  191 + return true;
171 } 192 }
172 193
173 void print_job::write_job(const uint8_t data[], size_t size) { 194 void print_job::write_job(const uint8_t data[], size_t size) {
@@ -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"));
@@ -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,68 +73,15 @@ std::wstring fromUtf8(std::string str) { @@ -73,68 +73,15 @@ 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();  
111 - return false;  
112 - }  
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);  
122 - }  
123 -  
124 - EndDoc(hDC);  
125 - DeleteDC(hDC);  
126 - FPDF_CloseDocument(doc);  
127 - FPDF_DestroyLibrary();  
128 - return true;  
129 -} 76 +bool PrintJob::printPdf(std::string name, std::string printer) {
  77 + documentName = name;
130 78
131 -bool PrintJob::printPdf(std::string name) { 79 + if (printer.empty()) {
132 PRINTDLG pd; 80 PRINTDLG pd;
133 DEVMODE* dm = static_cast<DEVMODE*>(GlobalAlloc(0, sizeof(DEVMODE))); 81 DEVMODE* dm = static_cast<DEVMODE*>(GlobalAlloc(0, sizeof(DEVMODE)));
134 ZeroMemory(dm, sizeof(DEVMODE)); 82 ZeroMemory(dm, sizeof(DEVMODE));
135 dm->dmFields = DM_ORIENTATION; 83 dm->dmFields = DM_ORIENTATION;
136 dm->dmOrientation = 2; 84 dm->dmOrientation = 2;
137 - printf("Printing ... \n");  
138 85
139 // Initialize PRINTDLG 86 // Initialize PRINTDLG
140 ZeroMemory(&pd, sizeof(pd)); 87 ZeroMemory(&pd, sizeof(pd));
@@ -156,34 +103,38 @@ bool PrintJob::printPdf(std::string name) { @@ -156,34 +103,38 @@ bool PrintJob::printPdf(std::string name) {
156 auto r = PrintDlg(&pd); 103 auto r = PrintDlg(&pd);
157 104
158 if (r == 1) { 105 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; 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) {
  113 + return false;
  114 + }
  115 + hDevMode = nullptr;
  116 + hDevNames = nullptr;
  117 + }
  118 +
  119 + auto dpiX = static_cast<double>(GetDeviceCaps(hDC, LOGPIXELSX)) / pdfDpi;
  120 + auto dpiY = static_cast<double>(GetDeviceCaps(hDC, LOGPIXELSY)) / pdfDpi;
161 auto pageWidth = 121 auto pageWidth =
162 - static_cast<double>(GetDeviceCaps(pd.hDC, PHYSICALWIDTH)) / dpiX; 122 + static_cast<double>(GetDeviceCaps(hDC, PHYSICALWIDTH)) / dpiX;
163 auto pageHeight = 123 auto pageHeight =
164 - static_cast<double>(GetDeviceCaps(pd.hDC, PHYSICALHEIGHT)) / dpiY;  
165 - auto printableWidth =  
166 - static_cast<double>(GetDeviceCaps(pd.hDC, HORZRES)) / dpiX; 124 + static_cast<double>(GetDeviceCaps(hDC, PHYSICALHEIGHT)) / dpiY;
  125 + auto printableWidth = static_cast<double>(GetDeviceCaps(hDC, HORZRES)) / dpiX;
167 auto printableHeight = 126 auto printableHeight =
168 - static_cast<double>(GetDeviceCaps(pd.hDC, VERTRES)) / dpiY; 127 + static_cast<double>(GetDeviceCaps(hDC, VERTRES)) / dpiY;
169 auto marginLeft = 128 auto marginLeft =
170 - static_cast<double>(GetDeviceCaps(pd.hDC, PHYSICALOFFSETX)) / dpiX; 129 + static_cast<double>(GetDeviceCaps(hDC, PHYSICALOFFSETX)) / dpiX;
171 auto marginTop = 130 auto marginTop =
172 - static_cast<double>(GetDeviceCaps(pd.hDC, PHYSICALOFFSETY)) / dpiY; 131 + static_cast<double>(GetDeviceCaps(hDC, PHYSICALOFFSETY)) / dpiY;
173 auto marginRight = pageWidth - printableWidth - marginLeft; 132 auto marginRight = pageWidth - printableWidth - marginLeft;
174 auto marginBottom = pageHeight - printableHeight - marginTop; 133 auto marginBottom = pageHeight - printableHeight - marginTop;
175 134
176 - hDC = pd.hDC;  
177 - hDevMode = pd.hDevMode;  
178 - hDevNames = pd.hDevNames;  
179 - documentName = name;  
180 -  
181 printing->onLayout(this, pageWidth, pageHeight, marginLeft, marginTop, 135 printing->onLayout(this, pageWidth, pageHeight, marginLeft, marginTop,
182 marginRight, marginBottom); 136 marginRight, marginBottom);
183 return true; 137 return true;
184 - }  
185 -  
186 - return false;  
187 } 138 }
188 139
189 std::vector<Printer> PrintJob::listPrinters() { 140 std::vector<Printer> PrintJob::listPrinters() {
@@ -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());