David PHAM-VAN

Implement missing Windows features

... ... @@ -4,6 +4,7 @@
- Fix Pdf Raster on WEB
- Fix Windows memory leaks
- Implement missing Windows features
## 3.7.0
... ...
... ... @@ -65,6 +65,9 @@ abstract class PrintingPlatform extends PlatformInterface {
PdfPageFormat format,
);
/// Enumerate the available printers on the system.
Future<List<Printer>> listPrinters();
/// Opens the native printer picker interface, and returns the URL of the selected printer.
Future<Printer> pickPrinter(Rect bounds);
... ...
... ... @@ -152,6 +152,26 @@ class MethodChannelPrinting extends PrintingPlatform {
}
@override
Future<List<Printer>> listPrinters() async {
final params = <String, dynamic>{};
final list =
await _channel.invokeMethod<List<dynamic>>('listPrinters', params);
final printers = <Printer>[];
for (final printer in list) {
printers.add(Printer(
url: printer['url'],
name: printer['name'],
model: printer['model'],
location: printer['location'],
));
}
return printers;
}
@override
Future<Printer> pickPrinter(Rect bounds) async {
final params = <String, dynamic>{
'x': bounds.left,
... ... @@ -191,7 +211,7 @@ class MethodChannelPrinting extends PrintingPlatform {
final params = <String, dynamic>{
'name': name,
'printer': printer.url,
'doc': Uint8List.fromList(bytes),
'doc': bytes,
'job': job.index,
};
await _channel.invokeMethod<int>('directPrintPdf', params);
... ...
... ... @@ -17,6 +17,7 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart' show Rect, Offset;
import 'package:meta/meta.dart';
import 'package:pdf/pdf.dart';
... ... @@ -48,15 +49,49 @@ mixin Printing {
return PrintingPlatform.instance.layoutPdf(onLayout, name, format);
}
/// Enumerate the available printers on the system.
///
/// This is not supported on all platforms. Check the result of [info] to
/// find at runtime if this feature is available or not.
static Future<List<Printer>> listPrinters() {
return PrintingPlatform.instance.listPrinters();
}
/// Opens the native printer picker interface, and returns the URL of the
/// selected printer.
///
/// This is not supported on all platforms. Check the result of [info] to
/// find at runtime if this feature is available or not.
static Future<Printer> pickPrinter({Rect bounds}) {
static Future<Printer> pickPrinter({
@required BuildContext context,
Rect bounds,
}) async {
final _info = await info();
if (_info != null && _info.canListPrinters) {
assert(
context != null,
'Pass a BuildCOntext to pickPrinter to display a selection list',
);
final printers = await listPrinters();
return await showDialog<Printer>(
context: context,
builder: (context) => SimpleDialog(
children: printers
.map<Widget>(
(e) => SimpleDialogOption(
child: Text(e.name),
onPressed: () => Navigator.of(context).pop(e),
),
)
.toList(),
),
);
}
bounds ??= Rect.fromCircle(center: Offset.zero, radius: 10);
return PrintingPlatform.instance.pickPrinter(bounds);
return await PrintingPlatform.instance.pickPrinter(bounds);
}
/// Prints a Pdf document to a specific local printer with no UI
... ...
... ... @@ -22,12 +22,14 @@ class PrintingInfo {
this.dynamicLayout = false,
this.canPrint = false,
this.canConvertHtml = false,
this.canListPrinters = false,
this.canShare = false,
this.canRaster = false,
}) : assert(directPrint != null),
assert(dynamicLayout != null),
assert(canPrint != null),
assert(canConvertHtml != null),
assert(canListPrinters != null),
assert(canShare != null),
assert(canRaster != null);
... ... @@ -37,6 +39,7 @@ class PrintingInfo {
dynamicLayout: map['dynamicLayout'] ?? false,
canPrint: map['canPrint'] ?? false,
canConvertHtml: map['canConvertHtml'] ?? false,
canListPrinters: map['canListPrinters'] ?? false,
canShare: map['canShare'] ?? false,
canRaster: map['canRaster'] ?? false,
);
... ... @@ -57,6 +60,9 @@ class PrintingInfo {
/// The platform implementation is able to convert an html document to Pdf
final bool canConvertHtml;
/// The platform implementation is able list the available printers on the system
final bool canListPrinters;
/// The platform implementation is able to share a Pdf document
/// to other applications
final bool canShare;
... ... @@ -71,6 +77,7 @@ class PrintingInfo {
directPrint: $directPrint
dynamicLayout: $dynamicLayout
canConvertHtml: $canConvertHtml
canListPrinters: $canListPrinters
canShare: $canShare
canRaster: $canRaster''';
... ... @@ -81,6 +88,7 @@ class PrintingInfo {
'directPrint': directPrint,
'dynamicLayout': dynamicLayout,
'canConvertHtml': canConvertHtml,
'canListPrinters': canListPrinters,
'canShare': canShare,
'canRaster': canRaster,
};
... ...
... ... @@ -52,10 +52,7 @@ class PrintingPlugin extends PrintingPlatform {
]);
return PrintingInfo(
directPrint: false,
dynamicLayout: false,
canPrint: true,
canConvertHtml: false,
canShare: true,
canRaster: workerSrc,
);
... ... @@ -159,6 +156,11 @@ class PrintingPlugin extends PrintingPlatform {
}
@override
Future<List<Printer>> listPrinters() {
throw UnimplementedError();
}
@override
Future<Printer> pickPrinter(
Rect bounds,
) {
... ...
... ... @@ -66,7 +66,7 @@ void main() {
test('pickPrinter', () async {
expect(
await Printing.pickPrinter(),
await Printing.pickPrinter(context: null),
null,
);
});
... ...
... ... @@ -30,16 +30,106 @@
namespace nfet {
const auto pdfDpi = 72;
std::string toUtf8(std::wstring wstr) {
int cbMultiByte =
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
LPSTR lpMultiByteStr = (LPSTR)malloc(cbMultiByte);
cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1,
lpMultiByteStr, cbMultiByte, NULL, NULL);
std::string ret = lpMultiByteStr;
free(lpMultiByteStr);
return ret;
}
std::string toUtf8(TCHAR* tstr) {
#ifndef UNICODE
#error "Non unicode build not supported"
#endif
if (!tstr) {
return std::string{};
}
return toUtf8(std::wstring{tstr});
}
std::wstring fromUtf8(std::string str) {
auto len = MultiByteToWideChar(CP_ACP, 0, str.c_str(),
static_cast<int>(str.length()), nullptr, 0);
if (len <= 0) {
return false;
}
auto wstr = std::wstring{};
wstr.resize(len);
MultiByteToWideChar(CP_ACP, 0, str.c_str(), static_cast<int>(str.length()),
&wstr[0], len);
return wstr;
}
PrintJob::PrintJob(Printing* printing, int index)
: printing(printing), index(index) {}
void PrintJob::directPrintPdf(std::string name,
bool PrintJob::directPrintPdf(std::string name,
std::vector<uint8_t> data,
std::string withPrinter) {}
std::string withPrinter) {
FPDF_InitLibraryWithConfig(nullptr);
auto doc = FPDF_LoadMemDocument64(data.data(), data.size(), nullptr);
if (!doc) {
FPDF_DestroyLibrary();
return false;
}
hDC = CreateDC(TEXT("WINSPOOL"), fromUtf8(withPrinter).c_str(), NULL, NULL);
if (!hDC) {
FPDF_CloseDocument(doc);
FPDF_DestroyLibrary();
return false;
}
DOCINFO docInfo;
ZeroMemory(&docInfo, sizeof(docInfo));
docInfo.cbSize = sizeof(DOCINFO);
auto docName = fromUtf8(name);
docInfo.lpszDocName = docName.c_str();
StartDoc(hDC, &docInfo);
int pageCount = FPDF_GetPageCount(doc);
for (auto i = 0; i < pageCount; i++) {
StartPage(hDC);
auto page = FPDF_LoadPage(doc, i);
if (!page) {
EndDoc(hDC);
DeleteDC(hDC);
FPDF_CloseDocument(doc);
FPDF_DestroyLibrary();
return false;
}
auto pageWidth = FPDF_GetPageWidth(page);
auto pageHeight = FPDF_GetPageHeight(page);
auto dpiX = GetDeviceCaps(hDC, LOGPIXELSX);
auto dpiY = GetDeviceCaps(hDC, LOGPIXELSY);
auto width = static_cast<int>(pageWidth / pdfDpi * dpiX);
auto height = static_cast<int>(pageHeight / pdfDpi * dpiY);
FPDF_RenderPage(hDC, page, 0, 0, width, height, 0, FPDF_ANNOT);
FPDF_ClosePage(page);
EndPage(hDC);
}
EndDoc(hDC);
DeleteDC(hDC);
FPDF_CloseDocument(doc);
FPDF_DestroyLibrary();
return true;
}
bool PrintJob::printPdf(std::string name) {
PRINTDLG pd;
// HWND hwnd;
// Initialize PRINTDLG
ZeroMemory(&pd, sizeof(pd));
... ... @@ -60,20 +150,8 @@ bool PrintJob::printPdf(std::string name) {
auto r = PrintDlg(&pd);
if (r == 1) {
// printf("ncopies: %d\n", pd.nCopies);
// printf("hDevMode: %d\n", (int)pd.hDevMode);
// DEVMODE* b = static_cast<DEVMODE*>(GlobalLock(pd.hDevMode));
// auto pageDpi = b->dmPrintQuality;
// GlobalUnlock(pd.hDevMode);
// auto pageHeight = b->dmPaperLength;
// auto pageWidth = b->dmPaperWidth;
// auto pageScale = b->dmScale / 100;
auto dpiX = static_cast<double>(GetDeviceCaps(pd.hDC, LOGPIXELSX)) / 72;
auto dpiY = static_cast<double>(GetDeviceCaps(pd.hDC, LOGPIXELSY)) / 72;
auto dpiX = static_cast<double>(GetDeviceCaps(pd.hDC, LOGPIXELSX)) / pdfDpi;
auto dpiY = static_cast<double>(GetDeviceCaps(pd.hDC, LOGPIXELSY)) / pdfDpi;
auto pageWidth =
static_cast<double>(GetDeviceCaps(pd.hDC, PHYSICALWIDTH)) / dpiX;
auto pageHeight =
... ... @@ -89,16 +167,10 @@ bool PrintJob::printPdf(std::string name) {
auto marginRight = pageWidth - printableWidth - marginLeft;
auto marginBottom = pageHeight - printableHeight - marginTop;
// printf("dpiX: %f\n", dpiX);
// printf("HORZRES: %d\n", GetDeviceCaps(pd.hDC, HORZRES));
// printf("PHYSICALOFFSETX: %d\n", GetDeviceCaps(pd.hDC, PHYSICALOFFSETX));
// printf("pageWidth: %f\n", pageWidth);
hDC = pd.hDC;
hDevMode = pd.hDevMode;
hDevNames = pd.hDevNames;
// printf("HDC: %llu job: %d\n", (size_t)pd.hDC, index);
documentName = name;
printing->onLayout(this, pageWidth, pageHeight, marginLeft, marginTop,
marginRight, marginBottom);
... ... @@ -108,111 +180,106 @@ bool PrintJob::printPdf(std::string name) {
return false;
}
std::vector<Printer> PrintJob::listPrinters() {
auto printers = std::vector<Printer>{};
DWORD needed = 0;
DWORD returned = 0;
const auto flags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS;
EnumPrinters(flags, nullptr, 1, nullptr, 0, &needed, &returned);
auto buffer = (PRINTER_INFO_1*)malloc(needed);
if (!buffer) {
return printers;
}
auto result = EnumPrinters(flags, nullptr, 1, (LPBYTE)buffer, needed, &needed,
&returned);
if (result == 0) {
free(buffer);
return printers;
}
for (DWORD i = 0; i < returned; i++) {
printers.push_back(Printer{
toUtf8(buffer[i].pName),
toUtf8(buffer[i].pName),
toUtf8(buffer[i].pDescription),
toUtf8(buffer[i].pComment),
});
}
free(buffer);
return printers;
}
void PrintJob::writeJob(std::vector<uint8_t> data) {
// printf("hDC: %llu job: %d\n", (size_t)hDC, index);
auto dpiX = static_cast<double>(GetDeviceCaps(hDC, LOGPIXELSX)) / 72;
auto dpiY = static_cast<double>(GetDeviceCaps(hDC, LOGPIXELSY)) / 72;
// GlobalFree(pd.hDevMode);
// print(
// 'Paper size: ${pageWidth} ${pageHeight} scale: $pageScale dpi:
// $pageDpi');
// final printerDC = CreateDCW(nullptr, szPrinter,nullptr,
// devmode);
DOCINFO info;
// memset(&info, 0, sizeof(info));
ZeroMemory(&info, sizeof(info));
info.cbSize = sizeof(info);
// info.fwType = 0;
// info.lpszDatatype = nullptr;
// info.lpszDocName = nullptr;
// info.lpszOutput = nullptr;
// auto printerDC = pd.hDC;
// print('hDC: ${pd.hDC}');
auto r = StartDoc(hDC, &info);
// print('StartDoc = $r');
auto dpiX = static_cast<double>(GetDeviceCaps(hDC, LOGPIXELSX)) / pdfDpi;
auto dpiY = static_cast<double>(GetDeviceCaps(hDC, LOGPIXELSY)) / pdfDpi;
FPDF_InitLibraryWithConfig(nullptr);
// final buffer = allocate<ffi.Uint8>(count : bytes.length);
// final nativeBuffer = buffer.asTypedList(bytes.length);
// nativeBuffer.setAll(0, bytes);
DOCINFO docInfo;
ZeroMemory(&docInfo, sizeof(docInfo));
docInfo.cbSize = sizeof(docInfo);
auto docName = fromUtf8(documentName);
docInfo.lpszDocName = docName.c_str();
// auto buffer = std::vector<uint8_t>{};
auto r = StartDoc(hDC, &docInfo);
FPDF_InitLibraryWithConfig(nullptr);
auto doc = FPDF_LoadMemDocument64(data.data(), data.size(), nullptr);
if (!doc) {
// printf("Error loading the document: %d\n", FPDF_GetLastError());
FPDF_DestroyLibrary();
return;
}
auto pages = FPDF_GetPageCount(doc);
// printf("Page count: %d\n", pages);
for (auto pageNum = 0; pageNum < pages; pageNum++) {
r = StartPage(hDC);
// printf("StartPage = %d\n", r);
auto page = FPDF_LoadPage(doc, pageNum);
// print(FPDF_GetLastError());
if (!page) {
EndPage(hDC);
continue;
}
auto pdfWidth = FPDF_GetPageWidth(page);
auto pdfHeight = FPDF_GetPageHeight(page);
// print('$width x $height');
// printf("pdfWidth: %f dpiX: %f \n", pdfWidth, dpiX);
int bWidth = static_cast<int>(pdfWidth * dpiX);
int bHeight = static_cast<int>(pdfHeight * dpiY);
// printf("bwidth/bheight: %d x %d\n", bWidth, bHeight);
FPDF_RenderPage(hDC, page, 0, 0, bWidth, bHeight, 0, FPDF_ANNOT);
r = EndPage(hDC);
// printf("EndPage = %d\n", r);
}
FPDF_CloseDocument(doc);
FPDF_DestroyLibrary();
r = EndDoc(hDC);
// printf("EndDoc = %d\n", r);
// DeleteDC(printerDC);
DeleteDC(hDC);
GlobalFree(hDevNames);
ClosePrinter(hDevMode);
} // namespace nfet
}
void PrintJob::cancelJob(std::string error) {}
bool PrintJob::sharePdf(std::vector<uint8_t> data, std::string name) {
TCHAR lpTempPathBuffer[MAX_PATH];
// TCHAR szTempFileName[MAX_PATH];
auto ret = GetTempPath(MAX_PATH, lpTempPathBuffer);
if (ret > MAX_PATH || (ret == 0)) {
return false;
}
#ifndef UNICODE
#error "Non unicode build not supported"
#endif
auto len = MultiByteToWideChar(CP_ACP, 0, name.c_str(),
static_cast<int>(name.length()), nullptr, 0);
if (len <= 0) {
return false;
}
auto filename = fromUtf8(toUtf8(lpTempPathBuffer) + "\\" + name);
auto w_name = std::wstring{};
w_name.resize(len);
MultiByteToWideChar(CP_ACP, 0, name.c_str(), static_cast<int>(name.length()),
&w_name[0], len);
auto filename = std::wstring{lpTempPathBuffer} + L"\\" + w_name;
auto output_file =
std::basic_ofstream<uint8_t>{filename, std::ios::out | std::ios::binary};
output_file.write(data.data(), data.size());
... ... @@ -231,7 +298,6 @@ bool PrintJob::sharePdf(std::vector<uint8_t> data, std::string name) {
ret = ShellExecuteEx(&ShExecInfo);
// CoTaskMemFree(pidlWinFiles);
return ret == TRUE;
}
... ... @@ -244,13 +310,12 @@ void PrintJob::rasterPdf(std::vector<uint8_t> data,
auto doc = FPDF_LoadMemDocument64(data.data(), data.size(), nullptr);
if (!doc) {
// printf(stderr, "Error: %d\n", FPDF_GetLastError());
FPDF_DestroyLibrary();
printing->onPageRasterEnd(this);
return;
}
auto pageCount = FPDF_GetPageCount(doc);
// printf("pdf: pages:%d\n", pageCount);
if (pages.size() == 0) {
// Use all pages
... ... @@ -265,15 +330,12 @@ void PrintJob::rasterPdf(std::vector<uint8_t> data,
auto page = FPDF_LoadPage(doc, n);
if (!page) {
// printf("Page Error: %d\n", FPDF_GetLastError());
continue;
}
auto width = FPDF_GetPageWidth(page);
auto height = FPDF_GetPageHeight(page);
// printf("pdf: page:%d w:%f h:%f\n", n, width, height);
auto bWidth = static_cast<int>(width * scale);
auto bHeight = static_cast<int>(height * scale);
... ... @@ -308,12 +370,13 @@ void PrintJob::rasterPdf(std::vector<uint8_t> data,
FPDF_DestroyLibrary();
printing->onPageRasterEnd(this);
} // namespace nfet
}
std::map<std::string, bool> PrintJob::printingInfo() {
return std::map<std::string, bool>{
{"directPrint", true}, {"dynamicLayout", true}, {"canPrint", true},
{"canConvertHtml", false}, {"canShare", true}, {"canRaster", true},
{"directPrint", true}, {"dynamicLayout", true}, {"canPrint", true},
{"canListPrinters", true}, {"canConvertHtml", false}, {"canShare", true},
{"canRaster", true},
};
}
... ...
... ... @@ -30,6 +30,19 @@ namespace nfet {
class Printing;
struct Printer {
const std::string name;
const std::string url;
const std::string model;
const std::string description;
Printer(std::string name,
std::string url,
std::string model,
std::string description)
: name(name), url(url), model(model), description(description) {}
};
class PrintJob {
private:
Printing* printing;
... ... @@ -37,17 +50,18 @@ class PrintJob {
HGLOBAL hDevMode = nullptr;
HGLOBAL hDevNames = nullptr;
HDC hDC = nullptr;
std::string documentName;
public:
PrintJob(Printing* printing, int index);
// ~PrintJob() { printf("Delete PrintJob #%d\n", index); }
int id() { return index; }
void directPrintPdf(std::string name,
std::vector<Printer> listPrinters();
bool directPrintPdf(std::string name,
std::vector<uint8_t> data,
std::string withPrinter);
std::string printer);
bool printPdf(std::string name);
... ...
... ... @@ -55,9 +55,7 @@ void Printing::onPageRasterEnd(PrintJob* job) {
class OnLayoutResult : public flutter::MethodResult<flutter::EncodableValue> {
public:
OnLayoutResult(PrintJob* job) : job(job) {
// printf("OnLayoutResult (%d) %p\n", job->id(), this);
}
OnLayoutResult(PrintJob* job) : job(job) {}
private:
PrintJob* job;
... ... @@ -65,7 +63,7 @@ class OnLayoutResult : public flutter::MethodResult<flutter::EncodableValue> {
protected:
void SuccessInternal(const flutter::EncodableValue* result) {
auto doc = std::get<std::vector<uint8_t>>(*result);
// printf("Success! (%d) %llu bytes %p\n", job->id(), doc.size(), this);
job->writeJob(doc);
delete job;
}
... ... @@ -73,14 +71,10 @@ class OnLayoutResult : public flutter::MethodResult<flutter::EncodableValue> {
void ErrorInternal(const std::string& error_code,
const std::string& error_message,
const flutter::EncodableValue* error_details) {
printf("Error!\n");
delete job;
}
void NotImplementedInternal() {
printf("NotImplemented!\n");
delete job;
}
void NotImplementedInternal() { delete job; }
};
void Printing::onLayout(PrintJob* job,
... ... @@ -90,12 +84,6 @@ void Printing::onLayout(PrintJob* job,
double marginTop,
double marginRight,
double marginBottom) {
// printf("onLayout (%d) %fx%f %f %f %f %f\n", job->id(), pageWidth,
// pageHeight,
// marginLeft, marginTop, marginRight, marginBottom);
// auto result = std::make_unique<OnLayoutResult>(job);
channel->InvokeMethod("onLayout",
std::make_unique<flutter::EncodableValue>(
flutter::EncodableValue(flutter::EncodableMap{
... ... @@ -117,4 +105,21 @@ void Printing::onLayout(PrintJob* job,
std::make_unique<OnLayoutResult>(job));
}
// send completion status to flutter
void Printing::onCompleted(PrintJob* job, bool completed, std::string error) {
auto map = flutter::EncodableMap{
{flutter::EncodableValue("job"), flutter::EncodableValue(job->id())},
{flutter::EncodableValue("completed"),
flutter::EncodableValue(completed)},
};
if (!error.empty()) {
map[flutter::EncodableValue("error")] = flutter::EncodableValue(error);
}
channel->InvokeMethod(
"onCompleted",
std::make_unique<flutter::EncodableValue>(flutter::EncodableValue(map)));
}
} // namespace nfet
... ...
... ... @@ -24,8 +24,6 @@
#include <flutter/method_channel.h>
// #include "print_job.h"
namespace nfet {
class PrintJob;
... ... @@ -51,6 +49,8 @@ class Printing {
double marginTop,
double marginRight,
double marginBottom);
void Printing::onCompleted(PrintJob* job, bool completed, std::string error);
};
} // namespace nfet
... ...
... ... @@ -58,6 +58,7 @@ class PrintingPlugin : public flutter::Plugin {
private:
Printing printing{};
// Called when a method is called on this plugin's channel from Dart.
void HandleMethodCall(
const flutter::MethodCall<flutter::EncodableValue>& method_call,
... ... @@ -66,9 +67,9 @@ class PrintingPlugin : public flutter::Plugin {
const auto* arguments =
std::get_if<flutter::EncodableMap>(method_call.arguments());
auto vName = arguments->find(flutter::EncodableValue("name"));
auto name = vName != arguments->end()
auto name = vName != arguments->end() && !vName->second.IsNull()
? std::get<std::string>(vName->second)
: std::string{};
: std::string{"document"};
auto vJob = arguments->find(flutter::EncodableValue("job"));
auto jobNum = vJob != arguments->end() ? std::get<int>(vJob->second) : -1;
auto job = new PrintJob{&printing, jobNum};
... ... @@ -78,14 +79,31 @@ class PrintingPlugin : public flutter::Plugin {
}
result->Success(flutter::EncodableValue(res ? 1 : 0));
} else if (method_call.method_name().compare("directPrintPdf") == 0) {
auto job = std::make_unique<PrintJob>(&printing, -1);
job->directPrintPdf("name", std::vector<uint8_t>{}, "withPrinter");
result->Success(nullptr);
const auto* arguments =
std::get_if<flutter::EncodableMap>(method_call.arguments());
auto vName = arguments->find(flutter::EncodableValue("name"));
auto name = vName != arguments->end() && !vName->second.IsNull()
? std::get<std::string>(vName->second)
: std::string{"document"};
auto vDoc = arguments->find(flutter::EncodableValue("doc"));
auto doc = vDoc != arguments->end()
? std::get<std::vector<uint8_t>>(vDoc->second)
: std::vector<uint8_t>{};
auto vPrinter = arguments->find(flutter::EncodableValue("printer"));
auto printer = vPrinter != arguments->end()
? std::get<std::string>(vPrinter->second)
: std::string{};
auto vJob = arguments->find(flutter::EncodableValue("job"));
auto jobNum = vJob != arguments->end() ? std::get<int>(vJob->second) : -1;
auto job = std::make_unique<PrintJob>(&printing, jobNum);
auto res = job->directPrintPdf(name, doc, printer);
result->Success(flutter::EncodableValue(1));
printing.onCompleted(job.get(), res, "");
} else if (method_call.method_name().compare("sharePdf") == 0) {
const auto* arguments =
std::get_if<flutter::EncodableMap>(method_call.arguments());
auto vName = arguments->find(flutter::EncodableValue("name"));
auto name = vName != arguments->end()
auto name = vName != arguments->end() && !vName->second.IsNull()
? std::get<std::string>(vName->second)
: std::string{"document.pdf"};
auto vDoc = arguments->find(flutter::EncodableValue("doc"));
... ... @@ -95,10 +113,23 @@ class PrintingPlugin : public flutter::Plugin {
auto job = std::make_unique<PrintJob>(&printing, -1);
auto res = job->sharePdf(doc, name);
result->Success(flutter::EncodableValue(res ? 1 : 0));
} else if (method_call.method_name().compare("pickPrinter") == 0) {
} else if (method_call.method_name().compare("listPrinters") == 0) {
auto job = std::make_unique<PrintJob>(&printing, -1);
job->pickPrinter(nullptr);
result->Success(nullptr);
auto printers = job->listPrinters();
auto pl = flutter::EncodableList{};
for (auto printer : printers) {
auto mp = flutter::EncodableMap{};
mp[flutter::EncodableValue("name")] =
flutter::EncodableValue(printer.name);
mp[flutter::EncodableValue("url")] =
flutter::EncodableValue(printer.url);
mp[flutter::EncodableValue("model")] =
flutter::EncodableValue(printer.model);
mp[flutter::EncodableValue("description")] =
flutter::EncodableValue(printer.description);
pl.push_back(mp);
}
result->Success(pl);
} else if (method_call.method_name().compare("rasterPdf") == 0) {
const auto* arguments =
std::get_if<flutter::EncodableMap>(method_call.arguments());
... ... @@ -106,18 +137,21 @@ class PrintingPlugin : public flutter::Plugin {
auto doc = vDoc != arguments->end()
? std::get<std::vector<uint8_t>>(vDoc->second)
: std::vector<uint8_t>{};
// auto vPages = arguments->find(flutter::EncodableValue("pages"));
// auto pages = vPages != arguments->end()
// ? std::get<flutter
// ::EncodableList>(vPages->second) : flutter
// ::EncodableList{};
auto vPages = arguments->find(flutter::EncodableValue("pages"));
auto lPages = vPages != arguments->end() && !vPages->second.IsNull()
? std::get<flutter::EncodableList>(vPages->second)
: flutter::EncodableList{};
auto pages = std::vector<int>{};
for (auto page : lPages) {
pages.push_back(std::get<int>(page));
}
auto vScale = arguments->find(flutter::EncodableValue("scale"));
auto scale =
vScale != arguments->end() ? std::get<double>(vScale->second) : 1;
auto vJob = arguments->find(flutter::EncodableValue("job"));
auto jobNum = vJob != arguments->end() ? std::get<int>(vJob->second) : -1;
auto job = std::make_unique<PrintJob>(&printing, jobNum);
job->rasterPdf(doc, std::vector<int>{}, scale);
job->rasterPdf(doc, pages, scale);
result->Success(nullptr);
} else if (method_call.method_name().compare("printingInfo") == 0) {
auto job = std::make_unique<PrintJob>(&printing, -1);
... ...