writeBytes method
Writes data as one RAW spooler job (Windows) or bulk transfer
(Android). Uses the connection opened by connect; if none is open,
opens one for this write and closes it again afterwards.
Implementation
@override
Future writeBytes(List<int> data, {int? vendorId, int? productId}) async {
if (Platform.isWindows) {
final ownHandle = _hPrinter == null;
PRINTER_HANDLE h;
try {
h = _hPrinter ?? _openWindowsPrinter();
} catch (e) {
return Future.error(e.toString());
}
final pDocName = 'My Document'.toNativeUtf16();
final pDataType = 'RAW'.toNativeUtf16();
final dwBytesWritten = calloc<DWORD>();
final docInfo = calloc<DOC_INFO_1>()
..ref.pDocName = PWSTR(pDocName)
..ref.pOutputFile = PWSTR(nullptr.cast<Utf16>())
..ref.pDatatype = PWSTR(pDataType);
var docStarted = false;
var pageStarted = false;
try {
if (StartDocPrinter(h, 1, docInfo) == 0) {
throw Exception('StartDocPrinter failed');
}
docStarted = true;
if (!StartPagePrinter(h)) throw Exception('StartPagePrinter failed');
pageStarted = true;
// Send in chunks: writing all at once makes some drivers paginate.
const int chunkSize = 4096;
int totalWritten = 0;
for (final chunk in data.chunkBy(chunkSize)) {
final lpData = chunk.toUint8();
try {
final ok = WritePrinter(h, lpData, chunk.length, dwBytesWritten);
if (!ok) {
throw Exception('WritePrinter failed after $totalWritten bytes');
}
totalWritten += dwBytesWritten.value;
} finally {
calloc.free(lpData);
}
}
pageStarted = false;
if (!EndPagePrinter(h)) throw Exception('EndPagePrinter failed');
docStarted = false;
if (!EndDocPrinter(h)) throw Exception('EndDocPrinter failed');
} catch (e) {
return Future.error(e.toString());
} finally {
if (pageStarted) EndPagePrinter(h);
if (docStarted) EndDocPrinter(h);
if (ownHandle) {
try {
ClosePrinter(h);
} catch (_) {}
}
calloc.free(docInfo);
calloc.free(dwBytesWritten);
calloc.free(pDocName);
calloc.free(pDataType);
}
} else if (Platform.isAndroid) {
final ownConnection = !_androidConnected;
try {
await connect();
// maxChunk limit on android
for (final chunk in data.chunkBy(16384)) {
final ok = await usbPrinter.write(Uint8List.fromList(chunk));
if (ok == false) throw Exception('USB write failed');
}
} catch (e) {
return Future.error(e.toString());
} finally {
if (ownConnection) await disconnect();
}
}
}