David PHAM-VAN

Use plugin_platform_interface

... ... @@ -34,11 +34,11 @@ printing/android/.gradle
pedantic_analyis_options_*.yaml
.dartfix
node_modules
pdf/lcov.info
pdf/coverage.json
lcov.info
coverage.json
.coverage
package-lock.json
printing/lcov.info
lcov.info
test/readme.dart
test/android
... ...
... ... @@ -77,7 +77,7 @@ test-pdf: $(FONTS) get-pdf .coverage
test-printing: $(FONTS) get-printing .coverage
cd printing; flutter test --coverage --coverage-path lcov.info
cd printing/example; flutter test --coverage --coverage-path ../lcov.info
cd printing/example; flutter test --coverage --coverage-path lcov.info
test-readme: $(FONTS) get-readme
cd test; dart extract_readme.dart
... ... @@ -88,7 +88,7 @@ test-web:
cd pdf/web_example; pub run webdev build
test: test-pdf test-printing node_modules test-web
cat pdf/lcov.info printing/lcov.info | node_modules/.bin/lcov-summary
cat pdf/lcov.info printing/lcov.info printing/example/lcov.info | node_modules/.bin/lcov-summary
clean:
git clean -fdx -e .vscode -e ref
... ...
... ... @@ -101,6 +101,14 @@ abstract class PdfFont extends PdfObject {
pdfDocument, 'ZapfDingbats', 0.820, -0.143, _zapfDingbatsWidths);
}
static const String _cannotDecodeMessage =
'''---------------------------------------------
Cannot decode the string to Latin1.
This font does not support Unicode characters.
If you want to use strings other than Latin strings, use a TrueType (TTF) font instead.
See https://github.com/DavBfr/dart_pdf/wiki/Fonts-Management
---------------------------------------------''';
/// The df type of the font, usually /Type1
final String subtype;
... ... @@ -141,13 +149,12 @@ abstract class PdfFont extends PdfObject {
final Uint8List chars = latin1.encode(s);
final Iterable<PdfFontMetrics> metrics = chars.map(glyphMetrics);
return PdfFontMetrics.append(metrics);
} catch (e) {
assert(false, '''\n---------------------------------------------
Can not decode the string to Latin1.
This font does not support Unicode characters.
If you want to use strings other than Latin strings, use a TrueType (TTF) font instead.
See https://github.com/DavBfr/dart_pdf/wiki/Fonts-Management
---------------------------------------------''');
} catch (_) {
assert(() {
print(_cannotDecodeMessage);
return true;
}());
rethrow;
}
}
... ... @@ -169,13 +176,12 @@ See https://github.com/DavBfr/dart_pdf/wiki/Fonts-Management
..putByte(40)
..putTextBytes(latin1.encode(text))
..putByte(41);
} catch (e) {
assert(false, '''\n---------------------------------------------
Can not decode the string to Latin1.
This font does not support Unicode characters.
If you want to use strings other than Latin strings, use a TrueType (TTF) font instead.
See https://github.com/DavBfr/dart_pdf/wiki/Fonts-Management
---------------------------------------------''');
} catch (_) {
assert(() {
print(_cannotDecodeMessage);
return true;
}());
rethrow;
}
}
... ...
# Changelog
## 3.2.0
- Update README
- Remove deprecated API
- Use plugin_platform_interface
- Fix inconsistent API
- Add Unit tests
## 3.1.0
- Migrate to the new Android plugins APIs
... ...
... ... @@ -63,11 +63,17 @@ class MyAppState extends State<MyApp> {
Future<void> _printPdf() async {
print('Print ...');
try {
final bool result = await Printing.layoutPdf(
onLayout: (PdfPageFormat format) async =>
(await generateDocument(format)).save());
_showPrintedToast(result);
} catch (e) {
final ScaffoldState scaffold = Scaffold.of(shareWidget.currentContext);
scaffold.showSnackBar(SnackBar(
content: Text('Error: ${e.toString()}'),
));
}
}
Future<void> _saveAsFile() async {
... ...
... ... @@ -14,22 +14,9 @@
* limitations under the License.
*/
library printing;
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart';
part 'src/asset_utils.dart';
part 'src/print_job.dart';
part 'src/printer.dart';
part 'src/printing.dart';
part 'src/printing_info.dart';
part 'src/raster.dart';
part 'src/widgets.dart';
export 'src/asset_utils.dart';
export 'src/callback.dart';
export 'src/printer.dart';
export 'src/printing.dart';
export 'src/printing_info.dart';
export 'src/raster.dart';
... ...
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
library printing_web;
import 'dart:async';
import 'dart:html' as html;
import 'dart:js' as js;
import 'package:flutter/services.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
part 'wsrc/print_job.dart';
class PrintingPlugin {
PrintingPlugin(this._channel);
static void registerWith(Registrar registrar) {
final MethodChannel channel = MethodChannel(
'net.nfet.printing',
const StandardMethodCodec(),
registrar.messenger,
);
final PrintingPlugin instance = PrintingPlugin(channel);
channel.setMethodCallHandler(instance.handleMethodCall);
}
final MethodChannel _channel;
Future<dynamic> handleMethodCall(MethodCall call) async {
switch (call.method) {
case 'printPdf':
final String name = call.arguments['name'];
final double width = call.arguments['width'];
final double height = call.arguments['height'];
final double marginLeft = call.arguments['marginLeft'];
final double marginTop = call.arguments['marginTop'];
final double marginRight = call.arguments['marginRight'];
final double marginBottom = call.arguments['marginBottom'];
final _PrintJob printJob = _PrintJob(this, call.arguments['job']);
return printJob.printPdf(name, width, height, marginLeft, marginTop,
marginRight, marginBottom);
case 'sharePdf':
final List<int> data = call.arguments['doc'];
final double x = call.arguments['x'];
final double y = call.arguments['y'];
final double width = call.arguments['w'];
final double height = call.arguments['h'];
final String name = call.arguments['name'];
return _PrintJob.sharePdf(data, x, y, width, height, name);
case 'printingInfo':
return _PrintJob.printingInfo();
}
throw UnimplementedError('Method "${call.method}" not implemented');
}
/// Request the Pdf document from flutter
Future<void> onLayout(
_PrintJob printJob,
double width,
double height,
double marginLeft,
double marginTop,
double marginRight,
double marginBottom) async {
final Map<String, dynamic> args = <String, dynamic>{
'width': width,
'height': height,
'marginLeft': marginLeft,
'marginTop': marginTop,
'marginRight': marginRight,
'marginBottom': marginBottom,
'job': printJob.index,
};
final dynamic result =
await _channel.invokeMethod<dynamic>('onLayout', args);
if (result is List<int>) {
printJob.setDocument(result);
} else {
printJob.cancelJob();
}
}
/// send completion status to flutter
Future<void> onCompleted(_PrintJob printJob, bool completed,
[String error = '']) async {
final Map<String, dynamic> data = <String, dynamic>{
'completed': completed,
'error': error,
'job': printJob.index,
};
await _channel.invokeMethod<dynamic>('onCompleted', data);
}
}
... ... @@ -14,7 +14,15 @@
* limitations under the License.
*/
part of printing;
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:meta/meta.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart';
/// Loads an image from a Flutter [ui.Image]
/// into a [PdfImage] instance
... ...
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'dart:async';
import 'package:pdf/pdf.dart';
/// Callback used to generate the Pdf document dynamically when the user
/// changes the page settings: size and margins
typedef LayoutCallback = FutureOr<List<int>> Function(PdfPageFormat format);
... ...
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'dart:async';
import 'package:flutter/rendering.dart' show Rect;
import 'package:pdf/pdf.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'callback.dart';
import 'method_channel.dart';
import 'printer.dart';
import 'printing_info.dart';
import 'raster.dart';
/// The interface that implementations of printing must implement.
abstract class PrintingPlatform extends PlatformInterface {
/// Constructs a UrlLauncherPlatform.
PrintingPlatform() : super(token: _token);
static final Object _token = Object();
static PrintingPlatform _instance = MethodChannelPrinting();
/// The default instance of [PrintingPlatform] to use.
///
/// Defaults to [MethodChannelPrinting].
static PrintingPlatform get instance => _instance;
/// Platform-specific plugins should set this with their own platform-specific
/// class that extends [PrintingPlatform] when they register themselves.
static set instance(PrintingPlatform instance) {
PlatformInterface.verifyToken(instance, _token);
_instance = instance;
}
/// Returns a [PrintingInfo] object representing the capabilities
/// supported for the current platform
Future<PrintingInfo> info();
/// Prints a Pdf document to a local printer using the platform UI
/// the Pdf document is re-built in a [LayoutCallback] each time the
/// user changes a setting like the page format or orientation.
///
/// returns a future with a `bool` set to true if the document is printed
/// and false if it is canceled.
/// throws an exception in case of error
Future<bool> layoutPdf(
LayoutCallback onLayout,
String name,
PdfPageFormat format,
);
/// Opens the native printer picker interface, and returns the URL of the selected printer.
Future<Printer> pickPrinter(Rect bounds);
/// Prints a Pdf document to a specific local printer with no UI
///
/// returns a future with a `bool` set to true if the document is printed
/// and false if it is canceled.
/// throws an exception in case of error
Future<bool> directPrintPdf(
Printer printer,
LayoutCallback onLayout,
String name,
PdfPageFormat format,
);
/// Displays a platform popup to share the Pdf document to another application
Future<bool> sharePdf(
List<int> bytes,
String filename,
Rect bounds,
);
/// Convert an html document to a pdf data
Future<List<int>> convertHtml(
String html,
String baseUrl,
PdfPageFormat format,
);
/// Convert a Pdf document to bitmap images
Stream<PdfRaster> raster(
List<int> document,
List<int> pages,
double dpi,
);
}
... ...
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/rendering.dart' show Rect;
import 'package:flutter/services.dart';
import 'package:pdf/pdf.dart';
import 'callback.dart';
import 'interface.dart';
import 'print_job.dart';
import 'printer.dart';
import 'printing_info.dart';
import 'raster.dart';
const MethodChannel _channel = MethodChannel('net.nfet.printing');
/// An implementation of [PrintingPlatform] that uses method channels.
class MethodChannelPrinting extends PrintingPlatform {
MethodChannelPrinting() : super() {
_channel.setMethodCallHandler(_handleMethod);
}
static final Map<int, PrintJob> _printJobs = <int, PrintJob>{};
static int _jobIndex = 0;
/// Callbacks from platform plugins
static Future<dynamic> _handleMethod(MethodCall call) async {
switch (call.method) {
case 'onLayout':
final PrintJob job = _printJobs[call.arguments['job']];
try {
final PdfPageFormat format = PdfPageFormat(
call.arguments['width'],
call.arguments['height'],
marginLeft: call.arguments['marginLeft'],
marginTop: call.arguments['marginTop'],
marginRight: call.arguments['marginRight'],
marginBottom: call.arguments['marginBottom'],
);
final List<int> bytes = await job.onLayout(format);
if (bytes == null) {
throw 'onLayout returned null';
}
return Uint8List.fromList(bytes);
} catch (e) {
return e.toString();
}
break;
case 'onCompleted':
final bool completed = call.arguments['completed'];
final String error = call.arguments['error'];
final PrintJob job = _printJobs[call.arguments['job']];
if (completed == false && error != null) {
job.onCompleted.completeError(error);
} else {
job.onCompleted.complete(completed);
}
break;
case 'onHtmlRendered':
final PrintJob job = _printJobs[call.arguments['job']];
job.onHtmlRendered.complete(call.arguments['doc']);
break;
case 'onHtmlError':
final PrintJob job = _printJobs[call.arguments['job']];
job.onHtmlRendered.completeError(call.arguments['error']);
break;
case 'onPageRasterized':
final PrintJob job = _printJobs[call.arguments['job']];
final PdfRaster raster = PdfRaster(
call.arguments['width'],
call.arguments['height'],
call.arguments['image'],
);
job.onPageRasterized.add(raster);
break;
case 'onPageRasterEnd':
final PrintJob job = _printJobs[call.arguments['job']];
job.onPageRasterized.close();
_printJobs.remove(job.index);
break;
}
}
static PrintJob _newPrintJob(PrintJob job) {
job.index = _jobIndex++;
_printJobs[job.index] = job;
return job;
}
@override
Future<PrintingInfo> info() async {
_channel.setMethodCallHandler(_handleMethod);
Map<dynamic, dynamic> result;
try {
result = await _channel.invokeMethod(
'printingInfo',
<String, dynamic>{},
);
} catch (e) {
print('Error getting printing info: $e');
return PrintingInfo.unavailable;
}
return PrintingInfo.fromMap(result);
}
@override
Future<bool> layoutPdf(
LayoutCallback onLayout,
String name,
PdfPageFormat format,
) async {
final PrintJob job = _newPrintJob(PrintJob(
onCompleted: Completer<bool>(),
onLayout: onLayout,
));
final Map<String, dynamic> params = <String, dynamic>{
'name': name,
'job': job.index,
'width': format.width,
'height': format.height,
'marginLeft': format.marginLeft,
'marginTop': format.marginTop,
'marginRight': format.marginRight,
'marginBottom': format.marginBottom,
};
await _channel.invokeMethod<int>('printPdf', params);
try {
return await job.onCompleted.future;
} finally {
_printJobs.remove(job.index);
}
}
@override
Future<Printer> pickPrinter(Rect bounds) async {
final Map<String, dynamic> params = <String, dynamic>{
'x': bounds.left,
'y': bounds.top,
'w': bounds.width,
'h': bounds.height,
};
final Map<dynamic, dynamic> printer = await _channel
.invokeMethod<Map<dynamic, dynamic>>('pickPrinter', params);
if (printer == null) {
return null;
}
return Printer(
url: printer['url'],
name: printer['name'],
model: printer['model'],
location: printer['location'],
);
}
@override
Future<bool> directPrintPdf(
Printer printer,
LayoutCallback onLayout,
String name,
PdfPageFormat format,
) async {
final PrintJob job = _newPrintJob(PrintJob(
onCompleted: Completer<bool>(),
));
final List<int> bytes = await onLayout(format);
if (bytes == null) {
return false;
}
final Map<String, dynamic> params = <String, dynamic>{
'name': name,
'printer': printer.url,
'doc': Uint8List.fromList(bytes),
'job': job.index,
};
await _channel.invokeMethod<int>('directPrintPdf', params);
final bool result = await job.onCompleted.future;
_printJobs.remove(job.index);
return result;
}
@override
Future<bool> sharePdf(
List<int> bytes,
String filename,
Rect bounds,
) async {
final Map<String, dynamic> params = <String, dynamic>{
'doc': Uint8List.fromList(bytes),
'name': filename,
'x': bounds.left,
'y': bounds.top,
'w': bounds.width,
'h': bounds.height,
};
return await _channel.invokeMethod('sharePdf', params);
}
@override
Future<List<int>> convertHtml(
String html, String baseUrl, PdfPageFormat format) async {
final PrintJob job = _newPrintJob(PrintJob(
onHtmlRendered: Completer<List<int>>(),
));
final Map<String, dynamic> params = <String, dynamic>{
'html': html,
'baseUrl': baseUrl,
'width': format.width,
'height': format.height,
'marginLeft': format.marginLeft,
'marginTop': format.marginTop,
'marginRight': format.marginRight,
'marginBottom': format.marginBottom,
'job': job.index,
};
await _channel.invokeMethod<void>('convertHtml', params);
final List<int> result = await job.onHtmlRendered.future;
_printJobs.remove(job.index);
return result;
}
@override
Stream<PdfRaster> raster(
List<int> document,
List<int> pages,
double dpi,
) {
final PrintJob job = _newPrintJob(PrintJob(
onPageRasterized: StreamController<PdfRaster>(),
));
final Map<String, dynamic> params = <String, dynamic>{
'doc': Uint8List.fromList(document),
'pages': pages,
'scale': dpi / PdfPageFormat.inch,
'job': job.index,
};
_channel.invokeMethod<void>('rasterPdf', params);
return job.onPageRasterized.stream;
}
}
... ...
... ... @@ -14,10 +14,13 @@
* limitations under the License.
*/
part of printing;
import 'dart:async';
class _PrintJob {
_PrintJob({
import 'callback.dart';
import 'raster.dart';
class PrintJob {
PrintJob({
this.onLayout,
this.onHtmlRendered,
this.onCompleted,
... ...
... ... @@ -14,10 +14,12 @@
* limitations under the License.
*/
part of printing;
import 'package:meta/meta.dart';
/// Information about a printer
@immutable
class Printer {
/// Create a printer information
const Printer({
@required this.url,
this.name,
... ... @@ -25,9 +27,16 @@ class Printer {
this.location,
}) : assert(url != null);
/// The platform specific printer identification
final String url;
/// The display name of the printer
final String name;
/// The printer model
final String model;
/// The physical location of the printer
final String location;
@override
... ...
... ... @@ -14,83 +14,19 @@
* limitations under the License.
*/
part of printing;
import 'dart:async';
typedef LayoutCallback = FutureOr<List<int>> Function(PdfPageFormat format);
import 'package:flutter/rendering.dart' show Rect, Offset;
import 'package:meta/meta.dart';
import 'package:pdf/pdf.dart';
mixin Printing {
static const MethodChannel _channel = MethodChannel('net.nfet.printing');
static final Map<int, _PrintJob> _printJobs = <int, _PrintJob>{};
static int _jobIndex = 0;
/// Callbacks from platform plugins
static Future<dynamic> _handleMethod(MethodCall call) async {
switch (call.method) {
case 'onLayout':
final _PrintJob job = _printJobs[call.arguments['job']];
try {
final PdfPageFormat format = PdfPageFormat(
call.arguments['width'],
call.arguments['height'],
marginLeft: call.arguments['marginLeft'],
marginTop: call.arguments['marginTop'],
marginRight: call.arguments['marginRight'],
marginBottom: call.arguments['marginBottom'],
);
final List<int> bytes = await job.onLayout(format);
if (bytes == null) {
return false;
}
return Uint8List.fromList(bytes);
} catch (e) {
print('Unable to print: $e');
return false;
}
break;
case 'onCompleted':
final bool completed = call.arguments['completed'];
final String error = call.arguments['error'];
final _PrintJob job = _printJobs[call.arguments['job']];
if (completed == false && error != null) {
job.onCompleted.completeError(error);
} else {
job.onCompleted.complete(completed);
}
break;
case 'onHtmlRendered':
final _PrintJob job = _printJobs[call.arguments['job']];
job.onHtmlRendered.complete(call.arguments['doc']);
break;
case 'onHtmlError':
final _PrintJob job = _printJobs[call.arguments['job']];
job.onHtmlRendered.completeError(call.arguments['error']);
break;
case 'onPageRasterized':
final _PrintJob job = _printJobs[call.arguments['job']];
final PdfRaster raster = PdfRaster._(
call.arguments['width'],
call.arguments['height'],
call.arguments['image'],
);
job.onPageRasterized.add(raster);
break;
case 'onPageRasterEnd':
final _PrintJob job = _printJobs[call.arguments['job']];
job.onPageRasterized.close();
_printJobs.remove(job.index);
break;
}
}
static _PrintJob _newPrintJob(_PrintJob job) {
job.index = _jobIndex++;
_printJobs[job.index] = job;
return job;
}
import 'callback.dart';
import 'interface.dart';
import 'printer.dart';
import 'printing_info.dart';
import 'raster.dart';
mixin Printing {
/// Prints a Pdf document to a local printer using the platform UI
/// the Pdf document is re-built in a [LayoutCallback] each time the
/// user changes a setting like the page format or orientation.
... ... @@ -102,61 +38,19 @@ mixin Printing {
@required LayoutCallback onLayout,
String name = 'Document',
PdfPageFormat format = PdfPageFormat.standard,
}) async {
_channel.setMethodCallHandler(_handleMethod);
final _PrintJob job = _newPrintJob(_PrintJob(
onCompleted: Completer<bool>(),
onLayout: onLayout,
));
final Map<String, dynamic> params = <String, dynamic>{
'name': name,
'job': job.index,
'width': format.width,
'height': format.height,
'marginLeft': format.marginLeft,
'marginTop': format.marginTop,
'marginRight': format.marginRight,
'marginBottom': format.marginBottom,
};
await _channel.invokeMethod<int>('printPdf', params);
try {
return await job.onCompleted.future;
} finally {
_printJobs.remove(job.index);
}
}
}) {
assert(onLayout != null);
assert(name != null);
assert(format != null);
static Future<Map<dynamic, dynamic>> printingInfo() async {
return await _channel.invokeMethod<Map<dynamic, dynamic>>(
'printingInfo',
<String, dynamic>{},
);
return PrintingPlatform.instance.layoutPdf(onLayout, name, format);
}
/// Opens the native printer picker interface, and returns the URL of the selected printer.
static Future<Printer> pickPrinter({Rect bounds}) async {
_channel.setMethodCallHandler(_handleMethod);
static Future<Printer> pickPrinter({Rect bounds}) {
bounds ??= Rect.fromCircle(center: Offset.zero, radius: 10);
final Map<String, dynamic> params = <String, dynamic>{
'x': bounds.left,
'y': bounds.top,
'w': bounds.width,
'h': bounds.height,
};
final Map<dynamic, dynamic> printer = await _channel
.invokeMethod<Map<dynamic, dynamic>>('pickPrinter', params);
if (printer == null) {
return null;
}
return Printer(
url: printer['url'],
name: printer['name'],
model: printer['model'],
location: printer['location'],
);
return PrintingPlatform.instance.pickPrinter(bounds);
}
/// Prints a Pdf document to a specific local printer with no UI
... ... @@ -164,60 +58,35 @@ mixin Printing {
/// returns a future with a `bool` set to true if the document is printed
/// and false if it is canceled.
/// throws an exception in case of error
static Future<bool> directPrintPdf({
static FutureOr<bool> directPrintPdf({
@required Printer printer,
@required LayoutCallback onLayout,
String name = 'Document',
PdfPageFormat format = PdfPageFormat.standard,
}) async {
}) {
if (printer == null) {
return false;
}
_channel.setMethodCallHandler(_handleMethod);
final _PrintJob job = _newPrintJob(_PrintJob(
onCompleted: Completer<bool>(),
));
final List<int> bytes = await onLayout(format);
if (bytes == null) {
return false;
}
final Map<String, dynamic> params = <String, dynamic>{
'name': name,
'printer': printer.url,
'doc': Uint8List.fromList(bytes),
'job': job.index,
};
await _channel.invokeMethod<int>('directPrintPdf', params);
final bool result = await job.onCompleted.future;
_printJobs.remove(job.index);
return result;
}
/// Prints a [PdfDocument] or a pdf stream to a local printer using the platform UI
@Deprecated('use Printing.layoutPdf(onLayout: (_) => document.save());')
static Future<void> printPdf({
@Deprecated('use bytes with document.save()') PdfDocument document,
List<int> bytes,
}) async {
assert(document != null || bytes != null);
assert(!(document == null && bytes == null));
assert(onLayout != null);
assert(name != null);
assert(format != null);
layoutPdf(
onLayout: (PdfPageFormat format) =>
document != null ? document.save() : bytes);
return PrintingPlatform.instance.directPrintPdf(
printer,
onLayout,
name,
format,
);
}
/// Displays a platform popup to share the Pdf document to another application
static Future<void> sharePdf({
static Future<bool> sharePdf({
@Deprecated('use bytes with document.save()') PdfDocument document,
List<int> bytes,
String filename = 'document.pdf',
Rect bounds,
}) async {
}) {
assert(document != null || bytes != null);
assert(!(document == null && bytes == null));
assert(filename != null);
... ... @@ -228,61 +97,40 @@ mixin Printing {
bounds ??= Rect.fromCircle(center: Offset.zero, radius: 10);
final Map<String, dynamic> params = <String, dynamic>{
'doc': Uint8List.fromList(bytes),
'name': filename,
'x': bounds.left,
'y': bounds.top,
'w': bounds.width,
'h': bounds.height,
};
return await _channel.invokeMethod('sharePdf', params);
return PrintingPlatform.instance.sharePdf(
bytes,
filename,
bounds,
);
}
/// Convert an html document to a pdf data
static Future<List<int>> convertHtml(
{@required String html,
static Future<List<int>> convertHtml({
@required String html,
String baseUrl,
PdfPageFormat format = PdfPageFormat.a4}) async {
_channel.setMethodCallHandler(_handleMethod);
final _PrintJob job = _newPrintJob(_PrintJob(
onHtmlRendered: Completer<List<int>>(),
));
final Map<String, dynamic> params = <String, dynamic>{
'html': html,
'baseUrl': baseUrl,
'width': format.width,
'height': format.height,
'marginLeft': format.marginLeft,
'marginTop': format.marginTop,
'marginRight': format.marginRight,
'marginBottom': format.marginBottom,
'job': job.index,
};
PdfPageFormat format = PdfPageFormat.standard,
}) {
assert(html != null);
assert(format != null);
await _channel.invokeMethod<void>('convertHtml', params);
final List<int> result = await job.onHtmlRendered.future;
_printJobs.remove(job.index);
return result;
return PrintingPlatform.instance.convertHtml(
html,
baseUrl,
format,
);
}
static Future<PrintingInfo> info() async {
_channel.setMethodCallHandler(_handleMethod);
Map<dynamic, dynamic> result;
try {
result = await _channel.invokeMethod(
'printingInfo',
<String, dynamic>{},
);
} catch (e) {
print('Error getting printing info: $e');
return PrintingInfo.unavailable;
/// Returns a [PrintingInfo] object representing the capabilities
/// supported for the current platform
static Future<PrintingInfo> info() {
return PrintingPlatform.instance.info();
}
return PrintingInfo.fromMap(result);
/// Returns a [PrintingInfo] object representing the capabilities
/// supported for the current platform as a map
@Deprecated('Use Printing.info()')
static Future<Map<dynamic, dynamic>> printingInfo() async {
return (await info()).asMap();
}
static Stream<PdfRaster> raster(
... ... @@ -290,20 +138,25 @@ mixin Printing {
List<int> pages,
double dpi = PdfPageFormat.inch,
}) {
_channel.setMethodCallHandler(_handleMethod);
assert(document != null);
assert(dpi != null);
assert(dpi > 0);
final _PrintJob job = _newPrintJob(_PrintJob(
onPageRasterized: StreamController<PdfRaster>(),
));
return PrintingPlatform.instance.raster(document, pages, dpi);
}
final Map<String, dynamic> params = <String, dynamic>{
'doc': Uint8List.fromList(document),
'pages': pages,
'scale': dpi / PdfPageFormat.inch,
'job': job.index,
};
/// Prints a [PdfDocument] or a pdf stream to a local printer
/// using the platform UI
@Deprecated('use Printing.layoutPdf(onLayout: (_) => document.save());')
static Future<void> printPdf({
@Deprecated('use bytes with document.save()') PdfDocument document,
List<int> bytes,
}) async {
assert(document != null || bytes != null);
assert(!(document == null && bytes == null));
_channel.invokeMethod<void>('rasterPdf', params);
return job.onPageRasterized.stream;
layoutPdf(
onLayout: (PdfPageFormat format) =>
document != null ? document.save() : bytes);
}
}
... ...
... ... @@ -14,19 +14,10 @@
* limitations under the License.
*/
part of printing;
/// Capabilities supported for the current platform
class PrintingInfo {
factory PrintingInfo.fromMap(Map<dynamic, dynamic> map) => PrintingInfo._(
directPrint: map['directPrint'] ?? false,
dynamicLayout: map['dynamicLayout'] ?? false,
canPrint: map['canPrint'],
canConvertHtml: map['canConvertHtml'],
canShare: map['canShare'],
canRaster: map['canRaster'],
);
const PrintingInfo._({
/// Create an information object
const PrintingInfo({
this.directPrint = false,
this.dynamicLayout = false,
this.canPrint = false,
... ... @@ -40,13 +31,38 @@ class PrintingInfo {
assert(canShare != null),
assert(canRaster != null);
static const PrintingInfo unavailable = PrintingInfo._();
/// Create an information object from a dictionnary
factory PrintingInfo.fromMap(Map<dynamic, dynamic> map) => PrintingInfo(
directPrint: map['directPrint'] ?? false,
dynamicLayout: map['dynamicLayout'] ?? false,
canPrint: map['canPrint'] ?? false,
canConvertHtml: map['canConvertHtml'] ?? false,
canShare: map['canShare'] ?? false,
canRaster: map['canRaster'] ?? false,
);
/// Default information with no feature available
static const PrintingInfo unavailable = PrintingInfo();
/// The platform can print directly to a printer
final bool directPrint;
/// The platform can request a dynamic layout when the user change
/// the printer or printer settings
final bool dynamicLayout;
/// The platform implementation is able to print a Pdf document
final bool canPrint;
/// The platform implementation is able to convert an html document to Pdf
final bool canConvertHtml;
/// The platform implementation is able to share a Pdf document
/// to other applications
final bool canShare;
/// The platform implementation is able to convert pages from a Pdf document
/// to a stream of images
final bool canRaster;
@override
... ...
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'dart:async';
import 'dart:convert';
import 'dart:html' as html;
import 'dart:js' as js;
import 'dart:typed_data';
import 'dart:ui';
import 'package:flutter/rendering.dart' show Rect;
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:pdf/pdf.dart';
import 'package:printing/src/raster.dart';
import 'package:printing/src/printer.dart';
import 'callback.dart';
import 'interface.dart';
import 'printing_info.dart';
class PrintingPlugin extends PrintingPlatform {
/// Registers this class as the default instance of [PrintingPlugin].
static void registerWith(Registrar registrar) {
PrintingPlatform.instance = PrintingPlugin();
}
@override
Future<PrintingInfo> info() async {
return const PrintingInfo(
directPrint: false,
dynamicLayout: false,
canPrint: true,
canConvertHtml: false,
canShare: true,
);
}
@override
Future<bool> layoutPdf(
LayoutCallback onLayout,
String name,
PdfPageFormat format,
) async {
final List<int> result = await onLayout(format);
if (result == null || result.isEmpty) {
return false;
}
final bool isChrome = js.context['chrome'] != null;
if (!isChrome) {
final String pr = 'data:application/pdf;base64,${base64.encode(result)}';
final html.Window win = js.context['window'];
win.open(pr, name);
return true;
}
final Completer<bool> completer = Completer<bool>();
final html.Blob pdfFile = html.Blob(
<Uint8List>[Uint8List.fromList(result)],
'application/pdf',
);
final String pdfUrl = html.Url.createObjectUrl(pdfFile);
final html.HtmlDocument doc = js.context['document'];
final html.IFrameElement frame = doc.createElement('iframe');
frame.setAttribute(
'style',
'visibility: hidden; height: 0; width: 0; position: absolute;',
// 'height: 400px; width: 600px; position: absolute; z-index: 1000',
);
frame.setAttribute('src', pdfUrl);
frame.addEventListener('load', (html.Event event) {
final js.JsObject win =
js.JsObject.fromBrowserObject(frame)['contentWindow'];
win.callMethod('addEventListener', <dynamic>[
'afterprint',
js.allowInterop<html.EventListener>((html.Event event) {
frame.remove();
completer.complete(true);
}),
]);
frame.focus();
win.callMethod('print');
});
doc.body.append(frame);
return completer.future;
}
@override
Future<bool> sharePdf(
List<int> bytes,
String filename,
Rect bounds,
) async {
final html.Blob pdfFile = html.Blob(
<Uint8List>[Uint8List.fromList(bytes)],
'application/pdf',
);
final String pdfUrl = html.Url.createObjectUrl(pdfFile);
final html.HtmlDocument doc = js.context['document'];
final html.AnchorElement link = doc.createElement('a');
link.href = pdfUrl;
link.download = filename;
link.click();
return true;
}
@override
Future<List<int>> convertHtml(
String html,
String baseUrl,
PdfPageFormat format,
) {
throw UnimplementedError();
}
@override
Future<bool> directPrintPdf(
Printer printer,
LayoutCallback onLayout,
String name,
PdfPageFormat format,
) {
throw UnimplementedError();
}
@override
Future<Printer> pickPrinter(
Rect bounds,
) {
throw UnimplementedError();
}
@override
Stream<PdfRaster> raster(
List<int> document,
List<int> pages,
double dpi,
) {
throw UnimplementedError();
}
}
... ...
... ... @@ -14,17 +14,28 @@
* limitations under the License.
*/
part of printing;
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/painting.dart';
/// Represents a bitmap image
class PdfRaster {
PdfRaster._(
/// Create a bitmap image
PdfRaster(
this.width,
this.height,
this.pixels,
);
/// The width of the image
final int width;
/// The height of the image
final int height;
/// The raw RGBA pixels of the image
final Uint8List pixels;
@override
... ... @@ -52,9 +63,12 @@ class PdfRaster {
}
}
/// Image provider for a [PdfRaster]
class PdfRasterImage extends ImageProvider<PdfRaster> {
/// Create an ImageProvider from a [PdfRaster]
PdfRasterImage(this.raster);
/// The image source
final PdfRaster raster;
Future<ImageInfo> _loadAsync() async {
... ...
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
part of printing;
@Deprecated('Use `Document` instead')
class PdfDoc extends Document {
/// Wrapper for a [Document] with zlib compression enabled by default
PdfDoc(
{bool compress = true,
PdfPageMode pageMode = PdfPageMode.none,
Theme theme,
String title,
String author,
String creator,
String subject,
String keywords,
String producer})
: super(
compress: compress,
pageMode: pageMode,
theme: theme,
title: title,
author: author,
creator: creator,
subject: subject,
keywords: keywords,
producer: producer,
) {
Document.debug = debugPaintSizeEnabled;
}
}
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
part of printing_web;
class _PrintJob {
_PrintJob(this.printing, this.index);
final PrintingPlugin printing;
final int index;
String _jobName;
Future<int> printPdf(
String name,
double width,
double height,
double marginLeft,
double marginTop,
double marginRight,
double marginBottom) async {
_jobName = name;
await printing.onLayout(
this, width, height, marginLeft, marginTop, marginRight, marginBottom);
return 1;
}
static Future<int> sharePdf(List<int> data, double x, double y, double width,
double height, String name) async {
final html.Blob pdfFile = html.Blob(<dynamic>[data], 'application/pdf');
final String pdfUrl = html.Url.createObjectUrl(pdfFile);
final html.HtmlDocument doc = js.context['document'];
final html.AnchorElement link = doc.createElement('a');
link.href = pdfUrl;
link.download = name;
link.click();
return 1;
}
static Map<String, dynamic> printingInfo() {
return <String, dynamic>{
'directPrint': false,
'dynamicLayout': false,
'canPrint': true,
'canConvertHtml': false,
'canShare': true,
};
}
void setDocument(List<int> result) {
final bool isChrome = js.context['chrome'] != null;
if (!isChrome) {
sharePdf(result, 0, 0, 0, 0, _jobName + '.pdf');
printing.onCompleted(this, true);
return;
}
final html.Blob pdfFile = html.Blob(<dynamic>[result], 'application/pdf');
final String pdfUrl = html.Url.createObjectUrl(pdfFile);
final html.HtmlDocument doc = js.context['document'];
final html.IFrameElement frame = doc.createElement('iframe');
frame.setAttribute('style',
'visibility: hidden; height: 0; width: 0; position: absolute;');
frame.setAttribute('src', pdfUrl);
doc.body.append(frame);
frame.addEventListener('load', (html.Event event) {
final js.JsObject win =
js.JsObject.fromBrowserObject(frame)['contentWindow'];
win.callMethod('addEventListener', <dynamic>[
'afterprint',
js.allowInterop<html.EventListener>((html.Event event) {
frame.remove();
printing.onCompleted(this, true);
}),
]);
frame.focus();
win.callMethod('print');
printing.onCompleted(this, true);
});
}
Future<void> cancelJob() async {}
}
... ... @@ -4,7 +4,7 @@ description: Plugin that allows Flutter apps to generate and print documents to
homepage: https://github.com/DavBfr/dart_pdf/tree/master/printing
repository: https://github.com/DavBfr/dart_pdf
issue_tracker: https://github.com/DavBfr/dart_pdf/issues
version: 3.1.0
version: 3.2.0
environment:
sdk: ">=2.3.0 <3.0.0"
... ... @@ -15,11 +15,13 @@ dependencies:
sdk: flutter
flutter_web_plugins:
sdk: flutter
pdf: "^1.3.15"
pdf: ^1.3.15
plugin_platform_interface: ^1.0.2
dev_dependencies:
flutter_test:
sdk: flutter
mockito: ^4.1.1
dependency_overrides:
pdf:
... ... @@ -36,5 +38,5 @@ flutter:
macos:
pluginClass: PrintingPlugin
web:
fileName: printing_web.dart
fileName: src/printing_web.dart
pluginClass: PrintingPlugin
... ...
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pdf;
import 'package:printing/printing.dart';
pdf.Document doc;
pdf.Font ttf;
void main() {
final String path =
Directory.current.path.split('/').last == 'test' ? '..' : '.';
const MethodChannel channel = MethodChannel('net.nfet.printing');
TestWidgetsFlutterBinding.ensureInitialized();
setUp(() {
channel.setMockMethodCallHandler((MethodCall methodCall) async {
print(methodCall);
return '1';
});
});
tearDown(() {
channel.setMockMethodCallHandler(null);
});
test('convertHtml', () async {
// expect(await Printing.platformVersion, '42');
});
test('pdfImageFromImageProvider(FileImage)', () async {
final PdfImage image = await pdfImageFromImageProvider(
pdf: doc.document, image: FileImage(File('$path/example.png')));
doc.addPage(
pdf.Page(
build: (pdf.Context context) => pdf.Center(
child: pdf.Container(
child: pdf.Image(image),
),
),
),
);
});
setUpAll(() {
pdf.Document.debug = true;
pdf.RichText.debug = true;
final Uint8List fontData =
File('$path/../pdf/open-sans.ttf').readAsBytesSync();
ttf = pdf.Font.ttf(fontData.buffer.asByteData());
doc = pdf.Document();
});
tearDownAll(() {
final File file = File('printing.pdf');
file.writeAsBytesSync(doc.save());
});
}
... ...
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'package:flutter_test/flutter_test.dart';
import 'package:printing/printing.dart';
void main() {
setUp(() {
TestWidgetsFlutterBinding.ensureInitialized();
});
test('PrintingInfo', () async {
final PrintingInfo info = PrintingInfo.unavailable;
expect(info.canConvertHtml, false);
expect(info.directPrint, false);
expect(info.dynamicLayout, false);
expect(info.canPrint, false);
expect(info.canConvertHtml, false);
expect(info.canShare, false);
expect(info.canRaster, false);
expect(info.toString(), isA<String>());
});
test('PrintingInfo.fromMap', () async {
final PrintingInfo info = PrintingInfo.fromMap(
<dynamic, dynamic>{
'canPrint': true,
},
);
expect(info.canConvertHtml, false);
expect(info.directPrint, false);
expect(info.dynamicLayout, false);
expect(info.canPrint, true);
expect(info.canConvertHtml, false);
expect(info.canShare, false);
expect(info.canRaster, false);
});
}
... ...
import 'dart:io';
import 'dart:typed_data';
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pdf;
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'package:printing/printing.dart';
pdf.Document doc;
pdf.Font ttf;
import 'package:printing/src/interface.dart';
void main() {
final String path =
Directory.current.path.split('/').last == 'test' ? '..' : '.';
const MethodChannel channel = MethodChannel('net.nfet.printing');
setUp(() {
TestWidgetsFlutterBinding.ensureInitialized();
final MockPrinting mock = MockPrinting();
PrintingPlatform.instance = mock;
});
setUp(() {
channel.setMockMethodCallHandler((MethodCall methodCall) async {
print(methodCall);
return '1';
test('info', () async {
final PrintingInfo info = await Printing.info();
expect(info, null);
});
test('layoutPdf', () async {
expect(
() async => await Printing.layoutPdf(onLayout: null),
throwsAssertionError,
);
expect(
await Printing.layoutPdf(
onLayout: (_) => null,
name: 'doc',
format: PdfPageFormat.letter,
),
null);
});
tearDown(() {
channel.setMockMethodCallHandler(null);
test('sharePdf', () async {
expect(
() async => await Printing.sharePdf(bytes: null),
throwsAssertionError,
);
expect(
await Printing.sharePdf(
bytes: <int>[],
),
null,
);
});
test('convertHtml', () async {
// expect(await Printing.platformVersion, '42');
test('pickPrinter', () async {
expect(
await Printing.pickPrinter(),
null,
);
});
test('pdfImageFromImageProvider(FileImage)', () async {
final PdfImage image = await pdfImageFromImageProvider(
pdf: doc.document, image: FileImage(File('$path/example.png')));
test('directPrintPdf', () async {
expect(
await Printing.directPrintPdf(onLayout: null, printer: null),
false,
);
doc.addPage(
pdf.Page(
build: (pdf.Context context) => pdf.Center(
child: pdf.Container(
child: pdf.Image(image),
),
expect(
() async => await Printing.directPrintPdf(
onLayout: null,
printer: const Printer(url: 'test'),
),
throwsAssertionError,
);
expect(
await Printing.directPrintPdf(
onLayout: (_) => null,
printer: const Printer(url: 'test'),
),
null,
);
});
setUpAll(() {
pdf.Document.debug = true;
pdf.RichText.debug = true;
final Uint8List fontData =
File('$path/../pdf/open-sans.ttf').readAsBytesSync();
ttf = pdf.Font.ttf(fontData.buffer.asByteData());
doc = pdf.Document();
test('convertHtml', () async {
expect(
await Printing.convertHtml(html: '<html></html>'),
null,
);
});
tearDownAll(() {
final File file = File('printing.pdf');
file.writeAsBytesSync(doc.save());
test('raster', () async {
expect(
() => Printing.raster(null),
throwsAssertionError,
);
expect(
Printing.raster(<int>[]),
null,
);
});
}
class MockPrinting extends Mock
with MockPlatformInterfaceMixin
implements PrintingPlatform {}
... ...
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:printing/printing.dart';
void main() {
setUp(() {
TestWidgetsFlutterBinding.ensureInitialized();
});
test('PdfRaster', () async {
final PdfRaster raster =
PdfRaster(10, 10, Uint8List.fromList(List<int>.filled(10 * 10 * 4, 0)));
expect(raster.toString(), 'Image 10x10 400 bytes');
expect(await raster.toImage(), isA<ui.Image>());
expect(await raster.toPng(), isA<Uint8List>());
});
testWidgets('PdfRasterImage', (WidgetTester tester) async {
final PdfRaster raster =
PdfRaster(10, 10, Uint8List.fromList(List<int>.filled(10 * 10 * 4, 0)));
await tester.pumpWidget(Image(image: PdfRasterImage(raster)));
await tester.pumpAndSettle();
});
}
... ...