Showing
13 changed files
with
181 additions
and
284 deletions
@@ -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()); |
-
Please register or login to post a comment