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