Showing
12 changed files
with
320 additions
and
135 deletions
@@ -65,6 +65,9 @@ abstract class PrintingPlatform extends PlatformInterface { | @@ -65,6 +65,9 @@ abstract class PrintingPlatform extends PlatformInterface { | ||
65 | PdfPageFormat format, | 65 | PdfPageFormat format, |
66 | ); | 66 | ); |
67 | 67 | ||
68 | + /// Enumerate the available printers on the system. | ||
69 | + Future<List<Printer>> listPrinters(); | ||
70 | + | ||
68 | /// Opens the native printer picker interface, and returns the URL of the selected printer. | 71 | /// Opens the native printer picker interface, and returns the URL of the selected printer. |
69 | Future<Printer> pickPrinter(Rect bounds); | 72 | Future<Printer> pickPrinter(Rect bounds); |
70 | 73 |
@@ -152,6 +152,26 @@ class MethodChannelPrinting extends PrintingPlatform { | @@ -152,6 +152,26 @@ class MethodChannelPrinting extends PrintingPlatform { | ||
152 | } | 152 | } |
153 | 153 | ||
154 | @override | 154 | @override |
155 | + Future<List<Printer>> listPrinters() async { | ||
156 | + final params = <String, dynamic>{}; | ||
157 | + final list = | ||
158 | + await _channel.invokeMethod<List<dynamic>>('listPrinters', params); | ||
159 | + | ||
160 | + final printers = <Printer>[]; | ||
161 | + | ||
162 | + for (final printer in list) { | ||
163 | + printers.add(Printer( | ||
164 | + url: printer['url'], | ||
165 | + name: printer['name'], | ||
166 | + model: printer['model'], | ||
167 | + location: printer['location'], | ||
168 | + )); | ||
169 | + } | ||
170 | + | ||
171 | + return printers; | ||
172 | + } | ||
173 | + | ||
174 | + @override | ||
155 | Future<Printer> pickPrinter(Rect bounds) async { | 175 | Future<Printer> pickPrinter(Rect bounds) async { |
156 | final params = <String, dynamic>{ | 176 | final params = <String, dynamic>{ |
157 | 'x': bounds.left, | 177 | 'x': bounds.left, |
@@ -191,7 +211,7 @@ class MethodChannelPrinting extends PrintingPlatform { | @@ -191,7 +211,7 @@ class MethodChannelPrinting extends PrintingPlatform { | ||
191 | final params = <String, dynamic>{ | 211 | final params = <String, dynamic>{ |
192 | 'name': name, | 212 | 'name': name, |
193 | 'printer': printer.url, | 213 | 'printer': printer.url, |
194 | - 'doc': Uint8List.fromList(bytes), | 214 | + 'doc': bytes, |
195 | 'job': job.index, | 215 | 'job': job.index, |
196 | }; | 216 | }; |
197 | await _channel.invokeMethod<int>('directPrintPdf', params); | 217 | await _channel.invokeMethod<int>('directPrintPdf', params); |
@@ -17,6 +17,7 @@ | @@ -17,6 +17,7 @@ | ||
17 | import 'dart:async'; | 17 | import 'dart:async'; |
18 | import 'dart:typed_data'; | 18 | import 'dart:typed_data'; |
19 | 19 | ||
20 | +import 'package:flutter/material.dart'; | ||
20 | import 'package:flutter/rendering.dart' show Rect, Offset; | 21 | import 'package:flutter/rendering.dart' show Rect, Offset; |
21 | import 'package:meta/meta.dart'; | 22 | import 'package:meta/meta.dart'; |
22 | import 'package:pdf/pdf.dart'; | 23 | import 'package:pdf/pdf.dart'; |
@@ -48,15 +49,49 @@ mixin Printing { | @@ -48,15 +49,49 @@ mixin Printing { | ||
48 | return PrintingPlatform.instance.layoutPdf(onLayout, name, format); | 49 | return PrintingPlatform.instance.layoutPdf(onLayout, name, format); |
49 | } | 50 | } |
50 | 51 | ||
52 | + /// Enumerate the available printers on the system. | ||
53 | + /// | ||
54 | + /// This is not supported on all platforms. Check the result of [info] to | ||
55 | + /// find at runtime if this feature is available or not. | ||
56 | + static Future<List<Printer>> listPrinters() { | ||
57 | + return PrintingPlatform.instance.listPrinters(); | ||
58 | + } | ||
59 | + | ||
51 | /// Opens the native printer picker interface, and returns the URL of the | 60 | /// Opens the native printer picker interface, and returns the URL of the |
52 | /// selected printer. | 61 | /// selected printer. |
53 | /// | 62 | /// |
54 | /// This is not supported on all platforms. Check the result of [info] to | 63 | /// This is not supported on all platforms. Check the result of [info] to |
55 | /// find at runtime if this feature is available or not. | 64 | /// find at runtime if this feature is available or not. |
56 | - static Future<Printer> pickPrinter({Rect bounds}) { | 65 | + static Future<Printer> pickPrinter({ |
66 | + @required BuildContext context, | ||
67 | + Rect bounds, | ||
68 | + }) async { | ||
69 | + final _info = await info(); | ||
70 | + | ||
71 | + if (_info != null && _info.canListPrinters) { | ||
72 | + assert( | ||
73 | + context != null, | ||
74 | + 'Pass a BuildCOntext to pickPrinter to display a selection list', | ||
75 | + ); | ||
76 | + final printers = await listPrinters(); | ||
77 | + return await showDialog<Printer>( | ||
78 | + context: context, | ||
79 | + builder: (context) => SimpleDialog( | ||
80 | + children: printers | ||
81 | + .map<Widget>( | ||
82 | + (e) => SimpleDialogOption( | ||
83 | + child: Text(e.name), | ||
84 | + onPressed: () => Navigator.of(context).pop(e), | ||
85 | + ), | ||
86 | + ) | ||
87 | + .toList(), | ||
88 | + ), | ||
89 | + ); | ||
90 | + } | ||
91 | + | ||
57 | bounds ??= Rect.fromCircle(center: Offset.zero, radius: 10); | 92 | bounds ??= Rect.fromCircle(center: Offset.zero, radius: 10); |
58 | 93 | ||
59 | - return PrintingPlatform.instance.pickPrinter(bounds); | 94 | + return await PrintingPlatform.instance.pickPrinter(bounds); |
60 | } | 95 | } |
61 | 96 | ||
62 | /// Prints a Pdf document to a specific local printer with no UI | 97 | /// Prints a Pdf document to a specific local printer with no UI |
@@ -22,12 +22,14 @@ class PrintingInfo { | @@ -22,12 +22,14 @@ class PrintingInfo { | ||
22 | this.dynamicLayout = false, | 22 | this.dynamicLayout = false, |
23 | this.canPrint = false, | 23 | this.canPrint = false, |
24 | this.canConvertHtml = false, | 24 | this.canConvertHtml = false, |
25 | + this.canListPrinters = false, | ||
25 | this.canShare = false, | 26 | this.canShare = false, |
26 | this.canRaster = false, | 27 | this.canRaster = false, |
27 | }) : assert(directPrint != null), | 28 | }) : assert(directPrint != null), |
28 | assert(dynamicLayout != null), | 29 | assert(dynamicLayout != null), |
29 | assert(canPrint != null), | 30 | assert(canPrint != null), |
30 | assert(canConvertHtml != null), | 31 | assert(canConvertHtml != null), |
32 | + assert(canListPrinters != null), | ||
31 | assert(canShare != null), | 33 | assert(canShare != null), |
32 | assert(canRaster != null); | 34 | assert(canRaster != null); |
33 | 35 | ||
@@ -37,6 +39,7 @@ class PrintingInfo { | @@ -37,6 +39,7 @@ class PrintingInfo { | ||
37 | dynamicLayout: map['dynamicLayout'] ?? false, | 39 | dynamicLayout: map['dynamicLayout'] ?? false, |
38 | canPrint: map['canPrint'] ?? false, | 40 | canPrint: map['canPrint'] ?? false, |
39 | canConvertHtml: map['canConvertHtml'] ?? false, | 41 | canConvertHtml: map['canConvertHtml'] ?? false, |
42 | + canListPrinters: map['canListPrinters'] ?? false, | ||
40 | canShare: map['canShare'] ?? false, | 43 | canShare: map['canShare'] ?? false, |
41 | canRaster: map['canRaster'] ?? false, | 44 | canRaster: map['canRaster'] ?? false, |
42 | ); | 45 | ); |
@@ -57,6 +60,9 @@ class PrintingInfo { | @@ -57,6 +60,9 @@ class PrintingInfo { | ||
57 | /// The platform implementation is able to convert an html document to Pdf | 60 | /// The platform implementation is able to convert an html document to Pdf |
58 | final bool canConvertHtml; | 61 | final bool canConvertHtml; |
59 | 62 | ||
63 | + /// The platform implementation is able list the available printers on the system | ||
64 | + final bool canListPrinters; | ||
65 | + | ||
60 | /// The platform implementation is able to share a Pdf document | 66 | /// The platform implementation is able to share a Pdf document |
61 | /// to other applications | 67 | /// to other applications |
62 | final bool canShare; | 68 | final bool canShare; |
@@ -71,6 +77,7 @@ class PrintingInfo { | @@ -71,6 +77,7 @@ class PrintingInfo { | ||
71 | directPrint: $directPrint | 77 | directPrint: $directPrint |
72 | dynamicLayout: $dynamicLayout | 78 | dynamicLayout: $dynamicLayout |
73 | canConvertHtml: $canConvertHtml | 79 | canConvertHtml: $canConvertHtml |
80 | + canListPrinters: $canListPrinters | ||
74 | canShare: $canShare | 81 | canShare: $canShare |
75 | canRaster: $canRaster'''; | 82 | canRaster: $canRaster'''; |
76 | 83 | ||
@@ -81,6 +88,7 @@ class PrintingInfo { | @@ -81,6 +88,7 @@ class PrintingInfo { | ||
81 | 'directPrint': directPrint, | 88 | 'directPrint': directPrint, |
82 | 'dynamicLayout': dynamicLayout, | 89 | 'dynamicLayout': dynamicLayout, |
83 | 'canConvertHtml': canConvertHtml, | 90 | 'canConvertHtml': canConvertHtml, |
91 | + 'canListPrinters': canListPrinters, | ||
84 | 'canShare': canShare, | 92 | 'canShare': canShare, |
85 | 'canRaster': canRaster, | 93 | 'canRaster': canRaster, |
86 | }; | 94 | }; |
@@ -52,10 +52,7 @@ class PrintingPlugin extends PrintingPlatform { | @@ -52,10 +52,7 @@ class PrintingPlugin extends PrintingPlatform { | ||
52 | ]); | 52 | ]); |
53 | 53 | ||
54 | return PrintingInfo( | 54 | return PrintingInfo( |
55 | - directPrint: false, | ||
56 | - dynamicLayout: false, | ||
57 | canPrint: true, | 55 | canPrint: true, |
58 | - canConvertHtml: false, | ||
59 | canShare: true, | 56 | canShare: true, |
60 | canRaster: workerSrc, | 57 | canRaster: workerSrc, |
61 | ); | 58 | ); |
@@ -159,6 +156,11 @@ class PrintingPlugin extends PrintingPlatform { | @@ -159,6 +156,11 @@ class PrintingPlugin extends PrintingPlatform { | ||
159 | } | 156 | } |
160 | 157 | ||
161 | @override | 158 | @override |
159 | + Future<List<Printer>> listPrinters() { | ||
160 | + throw UnimplementedError(); | ||
161 | + } | ||
162 | + | ||
163 | + @override | ||
162 | Future<Printer> pickPrinter( | 164 | Future<Printer> pickPrinter( |
163 | Rect bounds, | 165 | Rect bounds, |
164 | ) { | 166 | ) { |
@@ -30,16 +30,106 @@ | @@ -30,16 +30,106 @@ | ||
30 | 30 | ||
31 | namespace nfet { | 31 | namespace nfet { |
32 | 32 | ||
33 | +const auto pdfDpi = 72; | ||
34 | + | ||
35 | +std::string toUtf8(std::wstring wstr) { | ||
36 | + int cbMultiByte = | ||
37 | + WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL); | ||
38 | + LPSTR lpMultiByteStr = (LPSTR)malloc(cbMultiByte); | ||
39 | + cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, | ||
40 | + lpMultiByteStr, cbMultiByte, NULL, NULL); | ||
41 | + std::string ret = lpMultiByteStr; | ||
42 | + free(lpMultiByteStr); | ||
43 | + return ret; | ||
44 | +} | ||
45 | + | ||
46 | +std::string toUtf8(TCHAR* tstr) { | ||
47 | +#ifndef UNICODE | ||
48 | +#error "Non unicode build not supported" | ||
49 | +#endif | ||
50 | + | ||
51 | + if (!tstr) { | ||
52 | + return std::string{}; | ||
53 | + } | ||
54 | + | ||
55 | + return toUtf8(std::wstring{tstr}); | ||
56 | +} | ||
57 | + | ||
58 | +std::wstring fromUtf8(std::string str) { | ||
59 | + auto len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), | ||
60 | + static_cast<int>(str.length()), nullptr, 0); | ||
61 | + if (len <= 0) { | ||
62 | + return false; | ||
63 | + } | ||
64 | + | ||
65 | + auto wstr = std::wstring{}; | ||
66 | + wstr.resize(len); | ||
67 | + MultiByteToWideChar(CP_ACP, 0, str.c_str(), static_cast<int>(str.length()), | ||
68 | + &wstr[0], len); | ||
69 | + | ||
70 | + return wstr; | ||
71 | +} | ||
72 | + | ||
33 | PrintJob::PrintJob(Printing* printing, int index) | 73 | PrintJob::PrintJob(Printing* printing, int index) |
34 | : printing(printing), index(index) {} | 74 | : printing(printing), index(index) {} |
35 | 75 | ||
36 | -void PrintJob::directPrintPdf(std::string name, | 76 | +bool PrintJob::directPrintPdf(std::string name, |
37 | std::vector<uint8_t> data, | 77 | std::vector<uint8_t> data, |
38 | - std::string withPrinter) {} | 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 | +} | ||
39 | 130 | ||
40 | bool PrintJob::printPdf(std::string name) { | 131 | bool PrintJob::printPdf(std::string name) { |
41 | PRINTDLG pd; | 132 | PRINTDLG pd; |
42 | - // HWND hwnd; | ||
43 | 133 | ||
44 | // Initialize PRINTDLG | 134 | // Initialize PRINTDLG |
45 | ZeroMemory(&pd, sizeof(pd)); | 135 | ZeroMemory(&pd, sizeof(pd)); |
@@ -60,20 +150,8 @@ bool PrintJob::printPdf(std::string name) { | @@ -60,20 +150,8 @@ bool PrintJob::printPdf(std::string name) { | ||
60 | auto r = PrintDlg(&pd); | 150 | auto r = PrintDlg(&pd); |
61 | 151 | ||
62 | if (r == 1) { | 152 | if (r == 1) { |
63 | - // printf("ncopies: %d\n", pd.nCopies); | ||
64 | - // printf("hDevMode: %d\n", (int)pd.hDevMode); | ||
65 | - | ||
66 | - // DEVMODE* b = static_cast<DEVMODE*>(GlobalLock(pd.hDevMode)); | ||
67 | - // auto pageDpi = b->dmPrintQuality; | ||
68 | - | ||
69 | - // GlobalUnlock(pd.hDevMode); | ||
70 | - | ||
71 | - // auto pageHeight = b->dmPaperLength; | ||
72 | - // auto pageWidth = b->dmPaperWidth; | ||
73 | - // auto pageScale = b->dmScale / 100; | ||
74 | - | ||
75 | - auto dpiX = static_cast<double>(GetDeviceCaps(pd.hDC, LOGPIXELSX)) / 72; | ||
76 | - auto dpiY = static_cast<double>(GetDeviceCaps(pd.hDC, LOGPIXELSY)) / 72; | 153 | + auto dpiX = static_cast<double>(GetDeviceCaps(pd.hDC, LOGPIXELSX)) / pdfDpi; |
154 | + auto dpiY = static_cast<double>(GetDeviceCaps(pd.hDC, LOGPIXELSY)) / pdfDpi; | ||
77 | auto pageWidth = | 155 | auto pageWidth = |
78 | static_cast<double>(GetDeviceCaps(pd.hDC, PHYSICALWIDTH)) / dpiX; | 156 | static_cast<double>(GetDeviceCaps(pd.hDC, PHYSICALWIDTH)) / dpiX; |
79 | auto pageHeight = | 157 | auto pageHeight = |
@@ -89,16 +167,10 @@ bool PrintJob::printPdf(std::string name) { | @@ -89,16 +167,10 @@ bool PrintJob::printPdf(std::string name) { | ||
89 | auto marginRight = pageWidth - printableWidth - marginLeft; | 167 | auto marginRight = pageWidth - printableWidth - marginLeft; |
90 | auto marginBottom = pageHeight - printableHeight - marginTop; | 168 | auto marginBottom = pageHeight - printableHeight - marginTop; |
91 | 169 | ||
92 | - // printf("dpiX: %f\n", dpiX); | ||
93 | - // printf("HORZRES: %d\n", GetDeviceCaps(pd.hDC, HORZRES)); | ||
94 | - // printf("PHYSICALOFFSETX: %d\n", GetDeviceCaps(pd.hDC, PHYSICALOFFSETX)); | ||
95 | - // printf("pageWidth: %f\n", pageWidth); | ||
96 | - | ||
97 | hDC = pd.hDC; | 170 | hDC = pd.hDC; |
98 | hDevMode = pd.hDevMode; | 171 | hDevMode = pd.hDevMode; |
99 | hDevNames = pd.hDevNames; | 172 | hDevNames = pd.hDevNames; |
100 | - | ||
101 | - // printf("HDC: %llu job: %d\n", (size_t)pd.hDC, index); | 173 | + documentName = name; |
102 | 174 | ||
103 | printing->onLayout(this, pageWidth, pageHeight, marginLeft, marginTop, | 175 | printing->onLayout(this, pageWidth, pageHeight, marginLeft, marginTop, |
104 | marginRight, marginBottom); | 176 | marginRight, marginBottom); |
@@ -108,111 +180,106 @@ bool PrintJob::printPdf(std::string name) { | @@ -108,111 +180,106 @@ bool PrintJob::printPdf(std::string name) { | ||
108 | return false; | 180 | return false; |
109 | } | 181 | } |
110 | 182 | ||
183 | +std::vector<Printer> PrintJob::listPrinters() { | ||
184 | + auto printers = std::vector<Printer>{}; | ||
185 | + DWORD needed = 0; | ||
186 | + DWORD returned = 0; | ||
187 | + const auto flags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS; | ||
188 | + | ||
189 | + EnumPrinters(flags, nullptr, 1, nullptr, 0, &needed, &returned); | ||
190 | + | ||
191 | + auto buffer = (PRINTER_INFO_1*)malloc(needed); | ||
192 | + if (!buffer) { | ||
193 | + return printers; | ||
194 | + } | ||
195 | + | ||
196 | + auto result = EnumPrinters(flags, nullptr, 1, (LPBYTE)buffer, needed, &needed, | ||
197 | + &returned); | ||
198 | + | ||
199 | + if (result == 0) { | ||
200 | + free(buffer); | ||
201 | + return printers; | ||
202 | + } | ||
203 | + | ||
204 | + for (DWORD i = 0; i < returned; i++) { | ||
205 | + printers.push_back(Printer{ | ||
206 | + toUtf8(buffer[i].pName), | ||
207 | + toUtf8(buffer[i].pName), | ||
208 | + toUtf8(buffer[i].pDescription), | ||
209 | + toUtf8(buffer[i].pComment), | ||
210 | + }); | ||
211 | + } | ||
212 | + | ||
213 | + free(buffer); | ||
214 | + return printers; | ||
215 | +} | ||
216 | + | ||
111 | void PrintJob::writeJob(std::vector<uint8_t> data) { | 217 | void PrintJob::writeJob(std::vector<uint8_t> data) { |
112 | - // printf("hDC: %llu job: %d\n", (size_t)hDC, index); | ||
113 | - auto dpiX = static_cast<double>(GetDeviceCaps(hDC, LOGPIXELSX)) / 72; | ||
114 | - auto dpiY = static_cast<double>(GetDeviceCaps(hDC, LOGPIXELSY)) / 72; | ||
115 | - | ||
116 | - // GlobalFree(pd.hDevMode); | ||
117 | - | ||
118 | - // print( | ||
119 | - // 'Paper size: ${pageWidth} ${pageHeight} scale: $pageScale dpi: | ||
120 | - // $pageDpi'); | ||
121 | - | ||
122 | - // final printerDC = CreateDCW(nullptr, szPrinter,nullptr, | ||
123 | - // devmode); | ||
124 | - DOCINFO info; | ||
125 | - | ||
126 | - // memset(&info, 0, sizeof(info)); | ||
127 | - ZeroMemory(&info, sizeof(info)); | ||
128 | - info.cbSize = sizeof(info); | ||
129 | - // info.fwType = 0; | ||
130 | - // info.lpszDatatype = nullptr; | ||
131 | - // info.lpszDocName = nullptr; | ||
132 | - // info.lpszOutput = nullptr; | ||
133 | - // auto printerDC = pd.hDC; | ||
134 | - // print('hDC: ${pd.hDC}'); | ||
135 | - auto r = StartDoc(hDC, &info); | ||
136 | - // print('StartDoc = $r'); | 218 | + auto dpiX = static_cast<double>(GetDeviceCaps(hDC, LOGPIXELSX)) / pdfDpi; |
219 | + auto dpiY = static_cast<double>(GetDeviceCaps(hDC, LOGPIXELSY)) / pdfDpi; | ||
137 | 220 | ||
138 | - FPDF_InitLibraryWithConfig(nullptr); | ||
139 | - // final buffer = allocate<ffi.Uint8>(count : bytes.length); | ||
140 | - // final nativeBuffer = buffer.asTypedList(bytes.length); | ||
141 | - // nativeBuffer.setAll(0, bytes); | 221 | + DOCINFO docInfo; |
222 | + | ||
223 | + ZeroMemory(&docInfo, sizeof(docInfo)); | ||
224 | + docInfo.cbSize = sizeof(docInfo); | ||
225 | + | ||
226 | + auto docName = fromUtf8(documentName); | ||
227 | + docInfo.lpszDocName = docName.c_str(); | ||
142 | 228 | ||
143 | - // auto buffer = std::vector<uint8_t>{}; | 229 | + auto r = StartDoc(hDC, &docInfo); |
230 | + | ||
231 | + FPDF_InitLibraryWithConfig(nullptr); | ||
144 | 232 | ||
145 | auto doc = FPDF_LoadMemDocument64(data.data(), data.size(), nullptr); | 233 | auto doc = FPDF_LoadMemDocument64(data.data(), data.size(), nullptr); |
146 | if (!doc) { | 234 | if (!doc) { |
147 | - // printf("Error loading the document: %d\n", FPDF_GetLastError()); | 235 | + FPDF_DestroyLibrary(); |
148 | return; | 236 | return; |
149 | } | 237 | } |
150 | 238 | ||
151 | auto pages = FPDF_GetPageCount(doc); | 239 | auto pages = FPDF_GetPageCount(doc); |
152 | - // printf("Page count: %d\n", pages); | ||
153 | 240 | ||
154 | for (auto pageNum = 0; pageNum < pages; pageNum++) { | 241 | for (auto pageNum = 0; pageNum < pages; pageNum++) { |
155 | r = StartPage(hDC); | 242 | r = StartPage(hDC); |
156 | - // printf("StartPage = %d\n", r); | ||
157 | 243 | ||
158 | auto page = FPDF_LoadPage(doc, pageNum); | 244 | auto page = FPDF_LoadPage(doc, pageNum); |
159 | - // print(FPDF_GetLastError()); | 245 | + if (!page) { |
246 | + EndPage(hDC); | ||
247 | + continue; | ||
248 | + } | ||
160 | 249 | ||
161 | auto pdfWidth = FPDF_GetPageWidth(page); | 250 | auto pdfWidth = FPDF_GetPageWidth(page); |
162 | auto pdfHeight = FPDF_GetPageHeight(page); | 251 | auto pdfHeight = FPDF_GetPageHeight(page); |
163 | 252 | ||
164 | - // print('$width x $height'); | ||
165 | - | ||
166 | - // printf("pdfWidth: %f dpiX: %f \n", pdfWidth, dpiX); | ||
167 | int bWidth = static_cast<int>(pdfWidth * dpiX); | 253 | int bWidth = static_cast<int>(pdfWidth * dpiX); |
168 | int bHeight = static_cast<int>(pdfHeight * dpiY); | 254 | int bHeight = static_cast<int>(pdfHeight * dpiY); |
169 | 255 | ||
170 | - // printf("bwidth/bheight: %d x %d\n", bWidth, bHeight); | ||
171 | - | ||
172 | FPDF_RenderPage(hDC, page, 0, 0, bWidth, bHeight, 0, FPDF_ANNOT); | 256 | FPDF_RenderPage(hDC, page, 0, 0, bWidth, bHeight, 0, FPDF_ANNOT); |
173 | 257 | ||
174 | r = EndPage(hDC); | 258 | r = EndPage(hDC); |
175 | - // printf("EndPage = %d\n", r); | ||
176 | } | 259 | } |
177 | 260 | ||
178 | FPDF_CloseDocument(doc); | 261 | FPDF_CloseDocument(doc); |
179 | FPDF_DestroyLibrary(); | 262 | FPDF_DestroyLibrary(); |
180 | 263 | ||
181 | r = EndDoc(hDC); | 264 | r = EndDoc(hDC); |
182 | - // printf("EndDoc = %d\n", r); | ||
183 | - // DeleteDC(printerDC); | 265 | + |
184 | DeleteDC(hDC); | 266 | DeleteDC(hDC); |
185 | GlobalFree(hDevNames); | 267 | GlobalFree(hDevNames); |
186 | ClosePrinter(hDevMode); | 268 | ClosePrinter(hDevMode); |
187 | -} // namespace nfet | 269 | +} |
188 | 270 | ||
189 | void PrintJob::cancelJob(std::string error) {} | 271 | void PrintJob::cancelJob(std::string error) {} |
190 | 272 | ||
191 | bool PrintJob::sharePdf(std::vector<uint8_t> data, std::string name) { | 273 | bool PrintJob::sharePdf(std::vector<uint8_t> data, std::string name) { |
192 | TCHAR lpTempPathBuffer[MAX_PATH]; | 274 | TCHAR lpTempPathBuffer[MAX_PATH]; |
193 | - // TCHAR szTempFileName[MAX_PATH]; | ||
194 | 275 | ||
195 | auto ret = GetTempPath(MAX_PATH, lpTempPathBuffer); | 276 | auto ret = GetTempPath(MAX_PATH, lpTempPathBuffer); |
196 | if (ret > MAX_PATH || (ret == 0)) { | 277 | if (ret > MAX_PATH || (ret == 0)) { |
197 | return false; | 278 | return false; |
198 | } | 279 | } |
199 | 280 | ||
200 | -#ifndef UNICODE | ||
201 | -#error "Non unicode build not supported" | ||
202 | -#endif | ||
203 | - | ||
204 | - auto len = MultiByteToWideChar(CP_ACP, 0, name.c_str(), | ||
205 | - static_cast<int>(name.length()), nullptr, 0); | ||
206 | - if (len <= 0) { | ||
207 | - return false; | ||
208 | - } | 281 | + auto filename = fromUtf8(toUtf8(lpTempPathBuffer) + "\\" + name); |
209 | 282 | ||
210 | - auto w_name = std::wstring{}; | ||
211 | - w_name.resize(len); | ||
212 | - MultiByteToWideChar(CP_ACP, 0, name.c_str(), static_cast<int>(name.length()), | ||
213 | - &w_name[0], len); | ||
214 | - | ||
215 | - auto filename = std::wstring{lpTempPathBuffer} + L"\\" + w_name; | ||
216 | auto output_file = | 283 | auto output_file = |
217 | std::basic_ofstream<uint8_t>{filename, std::ios::out | std::ios::binary}; | 284 | std::basic_ofstream<uint8_t>{filename, std::ios::out | std::ios::binary}; |
218 | output_file.write(data.data(), data.size()); | 285 | output_file.write(data.data(), data.size()); |
@@ -231,7 +298,6 @@ bool PrintJob::sharePdf(std::vector<uint8_t> data, std::string name) { | @@ -231,7 +298,6 @@ bool PrintJob::sharePdf(std::vector<uint8_t> data, std::string name) { | ||
231 | 298 | ||
232 | ret = ShellExecuteEx(&ShExecInfo); | 299 | ret = ShellExecuteEx(&ShExecInfo); |
233 | 300 | ||
234 | - // CoTaskMemFree(pidlWinFiles); | ||
235 | return ret == TRUE; | 301 | return ret == TRUE; |
236 | } | 302 | } |
237 | 303 | ||
@@ -244,13 +310,12 @@ void PrintJob::rasterPdf(std::vector<uint8_t> data, | @@ -244,13 +310,12 @@ void PrintJob::rasterPdf(std::vector<uint8_t> data, | ||
244 | 310 | ||
245 | auto doc = FPDF_LoadMemDocument64(data.data(), data.size(), nullptr); | 311 | auto doc = FPDF_LoadMemDocument64(data.data(), data.size(), nullptr); |
246 | if (!doc) { | 312 | if (!doc) { |
247 | - // printf(stderr, "Error: %d\n", FPDF_GetLastError()); | 313 | + FPDF_DestroyLibrary(); |
248 | printing->onPageRasterEnd(this); | 314 | printing->onPageRasterEnd(this); |
249 | return; | 315 | return; |
250 | } | 316 | } |
251 | 317 | ||
252 | auto pageCount = FPDF_GetPageCount(doc); | 318 | auto pageCount = FPDF_GetPageCount(doc); |
253 | - // printf("pdf: pages:%d\n", pageCount); | ||
254 | 319 | ||
255 | if (pages.size() == 0) { | 320 | if (pages.size() == 0) { |
256 | // Use all pages | 321 | // Use all pages |
@@ -265,15 +330,12 @@ void PrintJob::rasterPdf(std::vector<uint8_t> data, | @@ -265,15 +330,12 @@ void PrintJob::rasterPdf(std::vector<uint8_t> data, | ||
265 | 330 | ||
266 | auto page = FPDF_LoadPage(doc, n); | 331 | auto page = FPDF_LoadPage(doc, n); |
267 | if (!page) { | 332 | if (!page) { |
268 | - // printf("Page Error: %d\n", FPDF_GetLastError()); | ||
269 | continue; | 333 | continue; |
270 | } | 334 | } |
271 | 335 | ||
272 | auto width = FPDF_GetPageWidth(page); | 336 | auto width = FPDF_GetPageWidth(page); |
273 | auto height = FPDF_GetPageHeight(page); | 337 | auto height = FPDF_GetPageHeight(page); |
274 | 338 | ||
275 | - // printf("pdf: page:%d w:%f h:%f\n", n, width, height); | ||
276 | - | ||
277 | auto bWidth = static_cast<int>(width * scale); | 339 | auto bWidth = static_cast<int>(width * scale); |
278 | auto bHeight = static_cast<int>(height * scale); | 340 | auto bHeight = static_cast<int>(height * scale); |
279 | 341 | ||
@@ -308,12 +370,13 @@ void PrintJob::rasterPdf(std::vector<uint8_t> data, | @@ -308,12 +370,13 @@ void PrintJob::rasterPdf(std::vector<uint8_t> data, | ||
308 | FPDF_DestroyLibrary(); | 370 | FPDF_DestroyLibrary(); |
309 | 371 | ||
310 | printing->onPageRasterEnd(this); | 372 | printing->onPageRasterEnd(this); |
311 | -} // namespace nfet | 373 | +} |
312 | 374 | ||
313 | std::map<std::string, bool> PrintJob::printingInfo() { | 375 | std::map<std::string, bool> PrintJob::printingInfo() { |
314 | return std::map<std::string, bool>{ | 376 | return std::map<std::string, bool>{ |
315 | - {"directPrint", true}, {"dynamicLayout", true}, {"canPrint", true}, | ||
316 | - {"canConvertHtml", false}, {"canShare", true}, {"canRaster", true}, | 377 | + {"directPrint", true}, {"dynamicLayout", true}, {"canPrint", true}, |
378 | + {"canListPrinters", true}, {"canConvertHtml", false}, {"canShare", true}, | ||
379 | + {"canRaster", true}, | ||
317 | }; | 380 | }; |
318 | } | 381 | } |
319 | 382 |
@@ -30,6 +30,19 @@ namespace nfet { | @@ -30,6 +30,19 @@ namespace nfet { | ||
30 | 30 | ||
31 | class Printing; | 31 | class Printing; |
32 | 32 | ||
33 | +struct Printer { | ||
34 | + const std::string name; | ||
35 | + const std::string url; | ||
36 | + const std::string model; | ||
37 | + const std::string description; | ||
38 | + | ||
39 | + Printer(std::string name, | ||
40 | + std::string url, | ||
41 | + std::string model, | ||
42 | + std::string description) | ||
43 | + : name(name), url(url), model(model), description(description) {} | ||
44 | +}; | ||
45 | + | ||
33 | class PrintJob { | 46 | class PrintJob { |
34 | private: | 47 | private: |
35 | Printing* printing; | 48 | Printing* printing; |
@@ -37,17 +50,18 @@ class PrintJob { | @@ -37,17 +50,18 @@ class PrintJob { | ||
37 | HGLOBAL hDevMode = nullptr; | 50 | HGLOBAL hDevMode = nullptr; |
38 | HGLOBAL hDevNames = nullptr; | 51 | HGLOBAL hDevNames = nullptr; |
39 | HDC hDC = nullptr; | 52 | HDC hDC = nullptr; |
53 | + std::string documentName; | ||
40 | 54 | ||
41 | public: | 55 | public: |
42 | PrintJob(Printing* printing, int index); | 56 | PrintJob(Printing* printing, int index); |
43 | 57 | ||
44 | - // ~PrintJob() { printf("Delete PrintJob #%d\n", index); } | ||
45 | - | ||
46 | int id() { return index; } | 58 | int id() { return index; } |
47 | 59 | ||
48 | - void directPrintPdf(std::string name, | 60 | + std::vector<Printer> listPrinters(); |
61 | + | ||
62 | + bool directPrintPdf(std::string name, | ||
49 | std::vector<uint8_t> data, | 63 | std::vector<uint8_t> data, |
50 | - std::string withPrinter); | 64 | + std::string printer); |
51 | 65 | ||
52 | bool printPdf(std::string name); | 66 | bool printPdf(std::string name); |
53 | 67 |
@@ -55,9 +55,7 @@ void Printing::onPageRasterEnd(PrintJob* job) { | @@ -55,9 +55,7 @@ void Printing::onPageRasterEnd(PrintJob* job) { | ||
55 | 55 | ||
56 | class OnLayoutResult : public flutter::MethodResult<flutter::EncodableValue> { | 56 | class OnLayoutResult : public flutter::MethodResult<flutter::EncodableValue> { |
57 | public: | 57 | public: |
58 | - OnLayoutResult(PrintJob* job) : job(job) { | ||
59 | - // printf("OnLayoutResult (%d) %p\n", job->id(), this); | ||
60 | - } | 58 | + OnLayoutResult(PrintJob* job) : job(job) {} |
61 | 59 | ||
62 | private: | 60 | private: |
63 | PrintJob* job; | 61 | PrintJob* job; |
@@ -65,7 +63,7 @@ class OnLayoutResult : public flutter::MethodResult<flutter::EncodableValue> { | @@ -65,7 +63,7 @@ class OnLayoutResult : public flutter::MethodResult<flutter::EncodableValue> { | ||
65 | protected: | 63 | protected: |
66 | void SuccessInternal(const flutter::EncodableValue* result) { | 64 | void SuccessInternal(const flutter::EncodableValue* result) { |
67 | auto doc = std::get<std::vector<uint8_t>>(*result); | 65 | auto doc = std::get<std::vector<uint8_t>>(*result); |
68 | - // printf("Success! (%d) %llu bytes %p\n", job->id(), doc.size(), this); | 66 | + |
69 | job->writeJob(doc); | 67 | job->writeJob(doc); |
70 | delete job; | 68 | delete job; |
71 | } | 69 | } |
@@ -73,14 +71,10 @@ class OnLayoutResult : public flutter::MethodResult<flutter::EncodableValue> { | @@ -73,14 +71,10 @@ class OnLayoutResult : public flutter::MethodResult<flutter::EncodableValue> { | ||
73 | void ErrorInternal(const std::string& error_code, | 71 | void ErrorInternal(const std::string& error_code, |
74 | const std::string& error_message, | 72 | const std::string& error_message, |
75 | const flutter::EncodableValue* error_details) { | 73 | const flutter::EncodableValue* error_details) { |
76 | - printf("Error!\n"); | ||
77 | delete job; | 74 | delete job; |
78 | } | 75 | } |
79 | 76 | ||
80 | - void NotImplementedInternal() { | ||
81 | - printf("NotImplemented!\n"); | ||
82 | - delete job; | ||
83 | - } | 77 | + void NotImplementedInternal() { delete job; } |
84 | }; | 78 | }; |
85 | 79 | ||
86 | void Printing::onLayout(PrintJob* job, | 80 | void Printing::onLayout(PrintJob* job, |
@@ -90,12 +84,6 @@ void Printing::onLayout(PrintJob* job, | @@ -90,12 +84,6 @@ void Printing::onLayout(PrintJob* job, | ||
90 | double marginTop, | 84 | double marginTop, |
91 | double marginRight, | 85 | double marginRight, |
92 | double marginBottom) { | 86 | double marginBottom) { |
93 | - // printf("onLayout (%d) %fx%f %f %f %f %f\n", job->id(), pageWidth, | ||
94 | - // pageHeight, | ||
95 | - // marginLeft, marginTop, marginRight, marginBottom); | ||
96 | - | ||
97 | - // auto result = std::make_unique<OnLayoutResult>(job); | ||
98 | - | ||
99 | channel->InvokeMethod("onLayout", | 87 | channel->InvokeMethod("onLayout", |
100 | std::make_unique<flutter::EncodableValue>( | 88 | std::make_unique<flutter::EncodableValue>( |
101 | flutter::EncodableValue(flutter::EncodableMap{ | 89 | flutter::EncodableValue(flutter::EncodableMap{ |
@@ -117,4 +105,21 @@ void Printing::onLayout(PrintJob* job, | @@ -117,4 +105,21 @@ void Printing::onLayout(PrintJob* job, | ||
117 | std::make_unique<OnLayoutResult>(job)); | 105 | std::make_unique<OnLayoutResult>(job)); |
118 | } | 106 | } |
119 | 107 | ||
108 | +// send completion status to flutter | ||
109 | +void Printing::onCompleted(PrintJob* job, bool completed, std::string error) { | ||
110 | + auto map = flutter::EncodableMap{ | ||
111 | + {flutter::EncodableValue("job"), flutter::EncodableValue(job->id())}, | ||
112 | + {flutter::EncodableValue("completed"), | ||
113 | + flutter::EncodableValue(completed)}, | ||
114 | + }; | ||
115 | + | ||
116 | + if (!error.empty()) { | ||
117 | + map[flutter::EncodableValue("error")] = flutter::EncodableValue(error); | ||
118 | + } | ||
119 | + | ||
120 | + channel->InvokeMethod( | ||
121 | + "onCompleted", | ||
122 | + std::make_unique<flutter::EncodableValue>(flutter::EncodableValue(map))); | ||
123 | +} | ||
124 | + | ||
120 | } // namespace nfet | 125 | } // namespace nfet |
@@ -24,8 +24,6 @@ | @@ -24,8 +24,6 @@ | ||
24 | 24 | ||
25 | #include <flutter/method_channel.h> | 25 | #include <flutter/method_channel.h> |
26 | 26 | ||
27 | -// #include "print_job.h" | ||
28 | - | ||
29 | namespace nfet { | 27 | namespace nfet { |
30 | 28 | ||
31 | class PrintJob; | 29 | class PrintJob; |
@@ -51,6 +49,8 @@ class Printing { | @@ -51,6 +49,8 @@ class Printing { | ||
51 | double marginTop, | 49 | double marginTop, |
52 | double marginRight, | 50 | double marginRight, |
53 | double marginBottom); | 51 | double marginBottom); |
52 | + | ||
53 | + void Printing::onCompleted(PrintJob* job, bool completed, std::string error); | ||
54 | }; | 54 | }; |
55 | 55 | ||
56 | } // namespace nfet | 56 | } // namespace nfet |
@@ -58,6 +58,7 @@ class PrintingPlugin : public flutter::Plugin { | @@ -58,6 +58,7 @@ class PrintingPlugin : public flutter::Plugin { | ||
58 | 58 | ||
59 | private: | 59 | private: |
60 | Printing printing{}; | 60 | Printing printing{}; |
61 | + | ||
61 | // Called when a method is called on this plugin's channel from Dart. | 62 | // Called when a method is called on this plugin's channel from Dart. |
62 | void HandleMethodCall( | 63 | void HandleMethodCall( |
63 | const flutter::MethodCall<flutter::EncodableValue>& method_call, | 64 | const flutter::MethodCall<flutter::EncodableValue>& method_call, |
@@ -66,9 +67,9 @@ class PrintingPlugin : public flutter::Plugin { | @@ -66,9 +67,9 @@ class PrintingPlugin : public flutter::Plugin { | ||
66 | const auto* arguments = | 67 | const auto* arguments = |
67 | std::get_if<flutter::EncodableMap>(method_call.arguments()); | 68 | std::get_if<flutter::EncodableMap>(method_call.arguments()); |
68 | auto vName = arguments->find(flutter::EncodableValue("name")); | 69 | auto vName = arguments->find(flutter::EncodableValue("name")); |
69 | - auto name = vName != arguments->end() | 70 | + auto name = vName != arguments->end() && !vName->second.IsNull() |
70 | ? std::get<std::string>(vName->second) | 71 | ? std::get<std::string>(vName->second) |
71 | - : std::string{}; | 72 | + : std::string{"document"}; |
72 | auto vJob = arguments->find(flutter::EncodableValue("job")); | 73 | auto vJob = arguments->find(flutter::EncodableValue("job")); |
73 | auto jobNum = vJob != arguments->end() ? std::get<int>(vJob->second) : -1; | 74 | auto jobNum = vJob != arguments->end() ? std::get<int>(vJob->second) : -1; |
74 | auto job = new PrintJob{&printing, jobNum}; | 75 | auto job = new PrintJob{&printing, jobNum}; |
@@ -78,14 +79,31 @@ class PrintingPlugin : public flutter::Plugin { | @@ -78,14 +79,31 @@ class PrintingPlugin : public flutter::Plugin { | ||
78 | } | 79 | } |
79 | result->Success(flutter::EncodableValue(res ? 1 : 0)); | 80 | result->Success(flutter::EncodableValue(res ? 1 : 0)); |
80 | } else if (method_call.method_name().compare("directPrintPdf") == 0) { | 81 | } else if (method_call.method_name().compare("directPrintPdf") == 0) { |
81 | - auto job = std::make_unique<PrintJob>(&printing, -1); | ||
82 | - job->directPrintPdf("name", std::vector<uint8_t>{}, "withPrinter"); | ||
83 | - result->Success(nullptr); | 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, ""); | ||
84 | } else if (method_call.method_name().compare("sharePdf") == 0) { | 102 | } else if (method_call.method_name().compare("sharePdf") == 0) { |
85 | const auto* arguments = | 103 | const auto* arguments = |
86 | std::get_if<flutter::EncodableMap>(method_call.arguments()); | 104 | std::get_if<flutter::EncodableMap>(method_call.arguments()); |
87 | auto vName = arguments->find(flutter::EncodableValue("name")); | 105 | auto vName = arguments->find(flutter::EncodableValue("name")); |
88 | - auto name = vName != arguments->end() | 106 | + auto name = vName != arguments->end() && !vName->second.IsNull() |
89 | ? std::get<std::string>(vName->second) | 107 | ? std::get<std::string>(vName->second) |
90 | : std::string{"document.pdf"}; | 108 | : std::string{"document.pdf"}; |
91 | auto vDoc = arguments->find(flutter::EncodableValue("doc")); | 109 | auto vDoc = arguments->find(flutter::EncodableValue("doc")); |
@@ -95,10 +113,23 @@ class PrintingPlugin : public flutter::Plugin { | @@ -95,10 +113,23 @@ class PrintingPlugin : public flutter::Plugin { | ||
95 | auto job = std::make_unique<PrintJob>(&printing, -1); | 113 | auto job = std::make_unique<PrintJob>(&printing, -1); |
96 | auto res = job->sharePdf(doc, name); | 114 | auto res = job->sharePdf(doc, name); |
97 | result->Success(flutter::EncodableValue(res ? 1 : 0)); | 115 | result->Success(flutter::EncodableValue(res ? 1 : 0)); |
98 | - } else if (method_call.method_name().compare("pickPrinter") == 0) { | 116 | + } else if (method_call.method_name().compare("listPrinters") == 0) { |
99 | auto job = std::make_unique<PrintJob>(&printing, -1); | 117 | auto job = std::make_unique<PrintJob>(&printing, -1); |
100 | - job->pickPrinter(nullptr); | ||
101 | - result->Success(nullptr); | 118 | + auto printers = job->listPrinters(); |
119 | + auto pl = flutter::EncodableList{}; | ||
120 | + for (auto printer : printers) { | ||
121 | + auto mp = flutter::EncodableMap{}; | ||
122 | + mp[flutter::EncodableValue("name")] = | ||
123 | + flutter::EncodableValue(printer.name); | ||
124 | + mp[flutter::EncodableValue("url")] = | ||
125 | + flutter::EncodableValue(printer.url); | ||
126 | + mp[flutter::EncodableValue("model")] = | ||
127 | + flutter::EncodableValue(printer.model); | ||
128 | + mp[flutter::EncodableValue("description")] = | ||
129 | + flutter::EncodableValue(printer.description); | ||
130 | + pl.push_back(mp); | ||
131 | + } | ||
132 | + result->Success(pl); | ||
102 | } else if (method_call.method_name().compare("rasterPdf") == 0) { | 133 | } else if (method_call.method_name().compare("rasterPdf") == 0) { |
103 | const auto* arguments = | 134 | const auto* arguments = |
104 | std::get_if<flutter::EncodableMap>(method_call.arguments()); | 135 | std::get_if<flutter::EncodableMap>(method_call.arguments()); |
@@ -106,18 +137,21 @@ class PrintingPlugin : public flutter::Plugin { | @@ -106,18 +137,21 @@ class PrintingPlugin : public flutter::Plugin { | ||
106 | auto doc = vDoc != arguments->end() | 137 | auto doc = vDoc != arguments->end() |
107 | ? std::get<std::vector<uint8_t>>(vDoc->second) | 138 | ? std::get<std::vector<uint8_t>>(vDoc->second) |
108 | : std::vector<uint8_t>{}; | 139 | : std::vector<uint8_t>{}; |
109 | - // auto vPages = arguments->find(flutter::EncodableValue("pages")); | ||
110 | - // auto pages = vPages != arguments->end() | ||
111 | - // ? std::get<flutter | ||
112 | - // ::EncodableList>(vPages->second) : flutter | ||
113 | - // ::EncodableList{}; | 140 | + auto vPages = arguments->find(flutter::EncodableValue("pages")); |
141 | + auto lPages = vPages != arguments->end() && !vPages->second.IsNull() | ||
142 | + ? std::get<flutter::EncodableList>(vPages->second) | ||
143 | + : flutter::EncodableList{}; | ||
144 | + auto pages = std::vector<int>{}; | ||
145 | + for (auto page : lPages) { | ||
146 | + pages.push_back(std::get<int>(page)); | ||
147 | + } | ||
114 | auto vScale = arguments->find(flutter::EncodableValue("scale")); | 148 | auto vScale = arguments->find(flutter::EncodableValue("scale")); |
115 | auto scale = | 149 | auto scale = |
116 | vScale != arguments->end() ? std::get<double>(vScale->second) : 1; | 150 | vScale != arguments->end() ? std::get<double>(vScale->second) : 1; |
117 | auto vJob = arguments->find(flutter::EncodableValue("job")); | 151 | auto vJob = arguments->find(flutter::EncodableValue("job")); |
118 | auto jobNum = vJob != arguments->end() ? std::get<int>(vJob->second) : -1; | 152 | auto jobNum = vJob != arguments->end() ? std::get<int>(vJob->second) : -1; |
119 | auto job = std::make_unique<PrintJob>(&printing, jobNum); | 153 | auto job = std::make_unique<PrintJob>(&printing, jobNum); |
120 | - job->rasterPdf(doc, std::vector<int>{}, scale); | 154 | + job->rasterPdf(doc, pages, scale); |
121 | result->Success(nullptr); | 155 | result->Success(nullptr); |
122 | } else if (method_call.method_name().compare("printingInfo") == 0) { | 156 | } else if (method_call.method_name().compare("printingInfo") == 0) { |
123 | auto job = std::make_unique<PrintJob>(&printing, -1); | 157 | auto job = std::make_unique<PrintJob>(&printing, -1); |
-
Please register or login to post a comment