David PHAM-VAN

Fix raster crash on all OS

# Changelog
## 5.2.2
- Fix raster crash on all OS.
## 5.2.1
- Fix Linux build
... ...
... ... @@ -194,9 +194,12 @@ public class PrintingHandler implements MethodChannel.MethodCallHandler {
/// The page has been converted to an image
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
void onPageRasterEnd(PrintingJob printJob) {
void onPageRasterEnd(PrintingJob printJob, String error) {
HashMap<String, Object> args = new HashMap<>();
args.put("job", printJob.index);
if (error != null) {
args.put("error", error);
}
channel.invokeMethod("onPageRasterEnd", args);
}
... ...
... ... @@ -434,8 +434,8 @@ public class PrintingJob extends PrintDocumentAdapter {
void rasterPdf(final byte[] data, final ArrayList<Integer> pages, final Double scale) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
Log.e("PDF", "PDF Raster available since Android 5.0 Lollipop (API 21)");
printing.onPageRasterEnd(this);
printing.onPageRasterEnd(
this, "PDF Raster available since Android 5.0 Lollipop (API 21)");
return;
}
... ... @@ -443,6 +443,7 @@ public class PrintingJob extends PrintDocumentAdapter {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void run() {
String error = null;
try {
File file = File.createTempFile("printing", null, null);
FileOutputStream oStream = new FileOutputStream(file);
... ... @@ -493,12 +494,14 @@ public class PrintingJob extends PrintDocumentAdapter {
} catch (IOException e) {
e.printStackTrace();
error = e.getMessage();
}
final String finalError = error;
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
printing.onPageRasterEnd(PrintingJob.this);
printing.onPageRasterEnd(PrintingJob.this, finalError);
}
});
}
... ...
... ... @@ -296,13 +296,17 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
public func rasterPdf(data: Data, pages: [Int]?, scale: CGFloat) {
let provider = CGDataProvider(data: data as CFData)!
let document = CGPDFDocument(provider)!
let document = CGPDFDocument(provider)
if document == nil {
printing.onPageRasterEnd(printJob: self, error: "Cannot raster a malformed PDF file")
return
}
DispatchQueue.global().async {
let pageCount = document.numberOfPages
let pageCount = document!.numberOfPages
for pageNum in pages ?? Array(0 ... pageCount - 1) {
guard let page = document.page(at: pageNum + 1) else { continue }
guard let page = document!.page(at: pageNum + 1) else { continue }
let angle = CGFloat(page.rotationAngle) * CGFloat.pi / -180
let rect = page.getBoxRect(.mediaBox)
let width = Int(abs((cos(angle) * rect.width + sin(angle) * rect.height) * scale))
... ... @@ -321,6 +325,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
space: rgb,
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue
)
if context != nil {
context!.translateBy(x: CGFloat(width) / 2, y: CGFloat(height) / 2)
context!.scaleBy(x: scale, y: scale)
... ... @@ -336,7 +341,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
}
DispatchQueue.main.sync {
self.printing.onPageRasterEnd(printJob: self)
self.printing.onPageRasterEnd(printJob: self, error: nil)
}
}
}
... ... @@ -349,6 +354,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
"canConvertHtml": true,
"canShare": true,
"canRaster": true,
"canListPrinters": false,
]
return data
}
... ...
... ... @@ -193,9 +193,10 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
channel.invokeMethod("onPageRasterized", arguments: data)
}
public func onPageRasterEnd(printJob: PrintJob) {
public func onPageRasterEnd(printJob: PrintJob, error: String?) {
let data: NSDictionary = [
"job": printJob.index,
"error": error as Any,
]
channel.invokeMethod("onPageRasterEnd", arguments: data)
}
... ...
... ... @@ -130,6 +130,10 @@ class MethodChannelPrinting extends PrintingPlatform {
case 'onPageRasterEnd':
final job = _printJobs.getJob(call.arguments['job']);
if (job != null) {
final dynamic error = call.arguments['error'];
if (error != null) {
job.onPageRasterized!.addError(error);
}
await job.onPageRasterized!.close();
_printJobs.remove(job.index);
}
... ...
... ... @@ -225,36 +225,56 @@ class _PdfPreviewState extends State<PdfPreview> {
});
}
var pageNum = 0;
await for (final PdfRaster page in Printing.raster(
_doc,
dpi: dpi,
pages: widget.pages,
)) {
if (!mounted) {
_rastering = false;
return;
}
setState(() {
if (pages.length <= pageNum) {
pages.add(_PdfPreviewPage(
page: page,
pdfPreviewPageDecoration: widget.pdfPreviewPageDecoration,
pageMargin: widget.previewPageMargin,
));
} else {
pages[pageNum] = _PdfPreviewPage(
page: page,
pdfPreviewPageDecoration: widget.pdfPreviewPageDecoration,
pageMargin: widget.previewPageMargin,
);
try {
var pageNum = 0;
await for (final PdfRaster page in Printing.raster(
_doc,
dpi: dpi,
pages: widget.pages,
)) {
if (!mounted) {
_rastering = false;
return;
}
});
setState(() {
if (pages.length <= pageNum) {
pages.add(_PdfPreviewPage(
page: page,
pdfPreviewPageDecoration: widget.pdfPreviewPageDecoration,
pageMargin: widget.previewPageMargin,
));
} else {
pages[pageNum] = _PdfPreviewPage(
page: page,
pdfPreviewPageDecoration: widget.pdfPreviewPageDecoration,
pageMargin: widget.previewPageMargin,
);
}
});
pageNum++;
pages.removeRange(pageNum, pages.length);
}
} catch (exception, stack) {
InformationCollector? collector;
assert(() {
collector = () sync* {
yield StringProperty('PageFormat', computedPageFormat.toString());
};
return true;
}());
pageNum++;
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'printing',
context: ErrorDescription('while generating a PDF'),
informationCollector: collector,
));
error = exception;
}
pages.removeRange(pageNum, pages.length);
_rastering = false;
}
... ...
... ... @@ -249,7 +249,7 @@ void print_job::raster_pdf(const uint8_t data[],
auto doc = FPDF_LoadMemDocument64(data, size, nullptr);
if (!doc) {
FPDF_DestroyLibrary();
on_page_raster_end(this);
on_page_raster_end(this, "Cannot raster a malformed PDF file");
return;
}
... ... @@ -307,7 +307,7 @@ void print_job::raster_pdf(const uint8_t data[],
FPDF_DestroyLibrary();
on_page_raster_end(this);
on_page_raster_end(this, nullptr);
}
FlValue* print_job::printing_info() {
... ...
... ... @@ -70,7 +70,7 @@ void on_page_rasterized(print_job* job,
int width,
int height);
void on_page_raster_end(print_job* job);
void on_page_raster_end(print_job* job, const char* error);
void on_layout(print_job* job,
double pageWidth,
... ...
... ... @@ -161,9 +161,12 @@ void on_page_rasterized(print_job* job,
nullptr, nullptr);
}
void on_page_raster_end(print_job* job) {
void on_page_raster_end(print_job* job, const char* error) {
g_autoptr(FlValue) map = fl_value_new_map();
fl_value_set_string(map, "job", fl_value_new_int(job->get_id()));
if (error != nullptr) {
fl_value_set_string(map, "error", fl_value_new_string(error));
}
fl_method_channel_invoke_method(channel, "onPageRasterEnd", map, nullptr,
nullptr, nullptr);
... ...
... ... @@ -242,13 +242,17 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
public func rasterPdf(data: Data, pages: [Int]?, scale: CGFloat) {
let provider = CGDataProvider(data: data as CFData)!
let document = CGPDFDocument(provider)!
let document = CGPDFDocument(provider)
if document == nil {
printing.onPageRasterEnd(printJob: self, error: "Cannot raster a malformed PDF file")
return
}
DispatchQueue.global().async {
let pageCount = document.numberOfPages
let pageCount = document!.numberOfPages
for pageNum in pages ?? Array(0 ... pageCount - 1) {
guard let page = document.page(at: pageNum + 1) else { continue }
guard let page = document!.page(at: pageNum + 1) else { continue }
let angle = CGFloat(page.rotationAngle) * CGFloat.pi / -180
let rect = page.getBoxRect(.mediaBox)
let width = Int(abs((cos(angle) * rect.width + sin(angle) * rect.height) * scale))
... ... @@ -283,7 +287,7 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
}
DispatchQueue.main.sync {
self.printing.onPageRasterEnd(printJob: self)
self.printing.onPageRasterEnd(printJob: self, error: nil)
}
}
}
... ... @@ -291,7 +295,7 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
public static func printingInfo() -> NSDictionary {
let data: NSDictionary = [
"directPrint": true,
"dynamicLayout": false,
"dynamicLayout": true,
"canPrint": true,
"canConvertHtml": true,
"canShare": true,
... ...
... ... @@ -188,9 +188,10 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
channel.invokeMethod("onPageRasterized", arguments: data)
}
public func onPageRasterEnd(printJob: PrintJob) {
public func onPageRasterEnd(printJob: PrintJob, error: String?) {
let data: NSDictionary = [
"job": printJob.index,
"error": error as Any,
]
channel.invokeMethod("onPageRasterEnd", arguments: data)
}
... ...
... ... @@ -7,7 +7,7 @@ description: >
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: 5.2.1
version: 5.2.2
environment:
sdk: ">=2.12.0-0 <3.0.0"
... ...
... ... @@ -289,7 +289,7 @@ void PrintJob::rasterPdf(std::vector<uint8_t> data,
auto doc = FPDF_LoadMemDocument64(data.data(), data.size(), nullptr);
if (!doc) {
FPDF_DestroyLibrary();
printing->onPageRasterEnd(this);
printing->onPageRasterEnd(this, "Cannot raster a malformed PDF file");
return;
}
... ... @@ -347,7 +347,7 @@ void PrintJob::rasterPdf(std::vector<uint8_t> data,
FPDF_DestroyLibrary();
printing->onPageRasterEnd(this);
printing->onPageRasterEnd(this, nullptr);
}
std::map<std::string, bool> PrintJob::printingInfo() {
... ...
... ... @@ -44,13 +44,18 @@ void Printing::onPageRasterized(std::vector<uint8_t> data,
})));
}
void Printing::onPageRasterEnd(PrintJob* job) {
channel->InvokeMethod("onPageRasterEnd",
std::make_unique<flutter::EncodableValue>(
flutter::EncodableValue(flutter::EncodableMap{
{flutter::EncodableValue("job"),
flutter::EncodableValue(job->id())},
})));
void Printing::onPageRasterEnd(PrintJob* job, const char* error) {
auto map = flutter::EncodableMap{
{flutter::EncodableValue("job"), flutter::EncodableValue(job->id())},
};
if (!error.empty()) {
map[flutter::EncodableValue("error")] = flutter::EncodableValue(error);
}
channel->InvokeMethod(
"onPageRasterEnd",
std::make_unique<flutter::EncodableValue>(flutter::EncodableValue(map)));
}
class OnLayoutResult : public flutter::MethodResult<flutter::EncodableValue> {
... ...
... ... @@ -40,7 +40,7 @@ class Printing {
int height,
PrintJob* job);
void onPageRasterEnd(PrintJob* job);
void onPageRasterEnd(PrintJob* job, const char* error);
void onLayout(PrintJob* job,
double pageWidth,
... ...