Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions printing/ios/printing/Sources/printing/PrintJob.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
controller.delegate = self

let printInfo = UIPrintInfo.printInfo()
printInfo.jobName = jobName!
let strippedJobName = jobName!.hasSuffix(".pdf") ? String(jobName!.dropLast(4)) : jobName!
printInfo.jobName = strippedJobName
printInfo.outputType = .general
if orientation != nil {
printInfo.orientation = orientation!
Expand Down Expand Up @@ -185,7 +186,8 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
orientation = UIPrintInfo.Orientation.landscape
}

jobName = name
// Strip .pdf extension as UIPrintInteractionController appends it automatically
jobName = name.hasSuffix(".pdf") ? String(name.dropLast(4)) : name
printerName = printerID

let controller = UIPrintInteractionController.shared
Expand Down
24 changes: 18 additions & 6 deletions printing/ios/printing/Sources/printing/PrintingPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,9 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
"job": printJob.index,
] as [String: Any]

channel.invokeMethod("onLayout", arguments: arg)
DispatchQueue.main.async {
self.channel.invokeMethod("onLayout", arguments: arg)
}
}

/// send completion status to flutter
Expand All @@ -195,8 +197,10 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
"error": error as Any,
"job": printJob.index,
]
channel.invokeMethod("onCompleted", arguments: data)
jobs.removeValue(forKey: UInt32(printJob.index))
DispatchQueue.main.async {
self.channel.invokeMethod("onCompleted", arguments: data)
}
}

/// send html to pdf data result to flutter
Expand All @@ -205,7 +209,9 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
"doc": FlutterStandardTypedData(bytes: pdfData),
"job": printJob.index,
]
channel.invokeMethod("onHtmlRendered", arguments: data)
DispatchQueue.main.async {
self.channel.invokeMethod("onHtmlRendered", arguments: data)
}
}

/// send html to pdf conversion error to flutter
Expand All @@ -214,7 +220,9 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
"error": error,
"job": printJob.index,
]
channel.invokeMethod("onHtmlError", arguments: data)
DispatchQueue.main.async {
self.channel.invokeMethod("onHtmlError", arguments: data)
}
}

/// send pdf to raster data result to flutter
Expand All @@ -225,14 +233,18 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
"height": height,
"job": printJob.index,
]
channel.invokeMethod("onPageRasterized", arguments: data)
DispatchQueue.main.async {
self.channel.invokeMethod("onPageRasterized", arguments: data)
}
}

public func onPageRasterEnd(printJob: PrintJob, error: String?) {
let data: NSDictionary = [
"job": printJob.index,
"error": error as Any,
]
channel.invokeMethod("onPageRasterEnd", arguments: data)
DispatchQueue.main.async {
self.channel.invokeMethod("onPageRasterEnd", arguments: data)
}
}
}
11 changes: 6 additions & 5 deletions printing/lib/printing_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@ class PrintingPlugin extends PrintingPlatform {
} else {
final pdfJsVersion =
web.window.hasProperty(_dartPdfJsVersion.toJS).toDart
? web.window
.getProperty<js.JSString?>(_dartPdfJsVersion.toJS)!
.toDart
: _pdfJsVersion;
? web.window
.getProperty<js.JSString?>(_dartPdfJsVersion.toJS)!
.toDart
: _pdfJsVersion;
_pdfJsUrlBase = '$_pdfJsCdnPath@$pdfJsVersion/build/';
}

Expand Down Expand Up @@ -159,6 +159,7 @@ class PrintingPlugin extends PrintingPlatform {
bool usePrinterSettings,
OutputType outputType,
bool forceCustomPrintPaper,
bool windowsModernDialog,
) async {
late Uint8List result;
try {
Expand Down Expand Up @@ -406,7 +407,7 @@ class PrintingPlugin extends PrintingPlatform {

class _WebPdfRaster extends PdfRaster {
_WebPdfRaster(int width, int height, this.png)
: super(width, height, Uint8List(0));
: super(width, height, Uint8List(0));

final Uint8List png;

Expand Down
1 change: 1 addition & 0 deletions printing/lib/src/interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ abstract class PrintingPlatform extends PlatformInterface {
bool usePrinterSettings,
OutputType outputType,
bool forceCustomPrintPaper,
bool windowsModernDialog,
);

/// Enumerate the available printers on the system.
Expand Down
2 changes: 2 additions & 0 deletions printing/lib/src/method_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ class MethodChannelPrinting extends PrintingPlatform {
bool usePrinterSettings,
OutputType outputType,
bool forceCustomPrintPaper,
bool windowsModernDialog,
) async {
final job = _printJobs.add(
onCompleted: Completer<bool>(),
Expand All @@ -200,6 +201,7 @@ class MethodChannelPrinting extends PrintingPlatform {
'usePrinterSettings': usePrinterSettings,
'outputType': outputType.index,
'forceCustomPrintPaper': forceCustomPrintPaper,
if (windowsModernDialog) 'windowsModernDialog': windowsModernDialog,
};

await _channel.invokeMethod<int>('printPdf', params);
Expand Down
3 changes: 2 additions & 1 deletion printing/lib/src/print_job.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

import 'dart:async';
import 'dart:math';
import 'dart:typed_data';

import 'callback.dart';
Expand Down Expand Up @@ -57,7 +58,7 @@ class PrintJobs {
/// Create a list print jobs
PrintJobs();

static var _currentIndex = 0;
static int _currentIndex = Random().nextInt(0x7FFFFFFF);

final _printJobs = <int, PrintJob>{};

Expand Down
4 changes: 4 additions & 0 deletions printing/lib/src/printing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ mixin Printing {
bool usePrinterSettings = false,
OutputType outputType = OutputType.generic,
bool forceCustomPrintPaper = false,
bool windowsModernDialog = false,
}) {
return PrintingPlatform.instance.layoutPdf(
null,
Expand All @@ -67,6 +68,7 @@ mixin Printing {
usePrinterSettings,
outputType,
forceCustomPrintPaper,
windowsModernDialog,
);
}

Expand Down Expand Up @@ -164,6 +166,7 @@ mixin Printing {
bool usePrinterSettings = false,
OutputType outputType = OutputType.generic,
bool forceCustomPrintPaper = false,
bool windowsModernDialog = false,
}) {
return PrintingPlatform.instance.layoutPdf(
printer,
Expand All @@ -174,6 +177,7 @@ mixin Printing {
usePrinterSettings,
outputType,
forceCustomPrintPaper,
windowsModernDialog,
);
}

Expand Down
49 changes: 40 additions & 9 deletions printing/macos/printing/Sources/printing/PrintJob.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
private var printOperation: NSPrintOperation?
private var pdfDocument: CGPDFDocument?
private var page: CGPDFPage?
private let semaphore = DispatchSemaphore(value: 0)
private var isWaitingForDocument = false
private var documentReceived = false
private var dynamic = false
private var _window: NSWindow?
private var lastLayoutParams: (width: CGFloat, height: CGFloat, marginLeft: CGFloat, marginTop: CGFloat, marginRight: CGFloat, marginBottom: CGFloat)?

public init(printing: PrintingPlugin, index: Int) {
self.printing = printing
Expand All @@ -44,6 +46,13 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
fatalError("init(coder:) has not been implemented")
}

private func layoutParamsChanged(_ new: (width: CGFloat, height: CGFloat, marginLeft: CGFloat, marginTop: CGFloat, marginRight: CGFloat, marginBottom: CGFloat)) -> Bool {
guard let last = lastLayoutParams else { return true }
return last.width != new.width || last.height != new.height ||
last.marginLeft != new.marginLeft || last.marginTop != new.marginTop ||
last.marginRight != new.marginRight || last.marginBottom != new.marginBottom
}

// Return the number of pages available for printing
override public func knowsPageRange(_ range: NSRangePointer) -> Bool {
let size = printOperation!.showsPrintPanel ? printOperation!.printPanel.printInfo.paperSize : printOperation!.printInfo.paperSize
Expand All @@ -52,18 +61,38 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
setBoundsSize(size)

if dynamic {
printing.onLayout(
printJob: self,
let currentParams = (
width: printOperation!.printInfo.paperSize.width,
height: printOperation!.printInfo.paperSize.height,
marginLeft: printOperation!.printInfo.leftMargin,
marginTop: printOperation!.printInfo.topMargin,
marginRight: printOperation!.printInfo.rightMargin,
marginBottom: printOperation!.printInfo.bottomMargin
)

// Block the main thread, waiting for a document
semaphore.wait()

if layoutParamsChanged(currentParams) {
lastLayoutParams = currentParams

printing.onLayout(
printJob: self,
width: currentParams.width,
height: currentParams.height,
marginLeft: currentParams.marginLeft,
marginTop: currentParams.marginTop,
marginRight: currentParams.marginRight,
marginBottom: currentParams.marginBottom
)

// Wait for document using RunLoop to keep main thread responsive
isWaitingForDocument = true
documentReceived = false
let runLoop = RunLoop.current
let timeout = Date(timeIntervalSinceNow: 30.0)
while !documentReceived && Date() < timeout {
runLoop.run(mode: .default, before: Date(timeIntervalSinceNow: 0.1))
}
isWaitingForDocument = false
}
}

if pdfDocument != nil {
Expand Down Expand Up @@ -95,8 +124,8 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
pdfDocument = CGPDFDocument(dataProvider!)

if dynamic {
// Unblock the main thread
semaphore.signal()
// Signal that document is ready
documentReceived = true
return
}

Expand Down Expand Up @@ -136,6 +165,7 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
public func printPdf(name: String, withPageSize size: CGSize, andMargin _: CGRect, withPrinter printer: String?, dynamically dyn: Bool, andWindow window: NSWindow) {
dynamic = dyn
_window = window
lastLayoutParams = nil
let sharedInfo = NSPrintInfo.shared
let sharedDict = sharedInfo.dictionary()
let printInfoDict = NSMutableDictionary(dictionary: sharedDict)
Expand Down Expand Up @@ -184,8 +214,9 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {

func cancelJob(_ error: String?) {
pdfDocument = nil
lastLayoutParams = nil
if dynamic {
semaphore.signal()
documentReceived = true
} else {
printing.onCompleted(printJob: self, completed: false, error: error as NSString?)
}
Expand Down
24 changes: 19 additions & 5 deletions printing/macos/printing/Sources/printing/PrintingPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ public func net_nfet_printing_set_error(job: UInt32, message: UnsafePointer<CCha
public class PrintingPlugin: NSObject, FlutterPlugin {
private static var instance: PrintingPlugin?
private var channel: FlutterMethodChannel
public var jobs = [UInt32: PrintJob]()
// Shared jobs across all plugin instances (for multi-window support)
private static var sharedJobs = [UInt32: PrintJob]()
private static let jobsLock = NSLock()
private var registrar: FlutterPluginRegistrar

init(_ channel: FlutterMethodChannel, _ registrar: FlutterPluginRegistrar) {
Expand All @@ -49,12 +51,18 @@ public class PrintingPlugin: NSObject, FlutterPlugin {

@objc
public static func setDocument(job: UInt32, doc: UnsafePointer<UInt8>, size: UInt64) {
instance!.jobs[job]?.setDocument(Data(bytes: doc, count: Int(size)))
jobsLock.lock()
let printJob = sharedJobs[job]
jobsLock.unlock()
printJob?.setDocument(Data(bytes: doc, count: Int(size)))
}

@objc
public static func setError(job: UInt32, message: UnsafePointer<CChar>) {
instance!.jobs[job]?.cancelJob(String(cString: message))
jobsLock.lock()
let printJob = sharedJobs[job]
jobsLock.unlock()
printJob?.cancelJob(String(cString: message))
}

/// Entry point
Expand All @@ -78,7 +86,10 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
let marginBottom = CGFloat((args["marginBottom"] as! NSNumber).floatValue)
let printJob = PrintJob(printing: self, index: args["job"] as! Int)
let dynamic = args["dynamic"] as! Bool
jobs[args["job"] as! UInt32] = printJob

PrintingPlugin.jobsLock.lock()
PrintingPlugin.sharedJobs[args["job"] as! UInt32] = printJob
PrintingPlugin.jobsLock.unlock()

guard let window = registrar.view?.window else {
result(NSNumber(value: 0))
Expand Down Expand Up @@ -191,7 +202,10 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
"job": printJob.index,
]
channel.invokeMethod("onCompleted", arguments: data)
jobs.removeValue(forKey: UInt32(printJob.index))

PrintingPlugin.jobsLock.lock()
PrintingPlugin.sharedJobs.removeValue(forKey: UInt32(printJob.index))
PrintingPlugin.jobsLock.unlock()
}

/// send html to pdf data result to flutter
Expand Down
4 changes: 2 additions & 2 deletions printing/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ dependencies:
http: ">=0.13.0 <2.0.0"
image: ">=4.1.0 <=5.0.0"
meta: ">=1.3.0 <2.0.0"
pdf: ^3.10.0
pdf: ^3.12.0
pdf_widget_wrapper: '>=1.0.4 <2.0.0'
plugin_platform_interface: ^2.1.0
web: ^1.0.0
Expand All @@ -45,7 +45,7 @@ dependency_overrides:
pdf:
path: ../pdf
pdf_widget_wrapper:
path: ../widget_wrapper
path: ../widget_wrapper

flutter:
plugin:
Expand Down
7 changes: 5 additions & 2 deletions printing/test/printing_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ class MockPrinting extends Mock
bool usePrinterSettings,
OutputType outputType,
bool forceCustomPrintPaper,
) async => true;
bool windowsModernDialog,
) async =>
true;

@override
Future<bool> sharePdf(
Expand All @@ -109,7 +111,8 @@ class MockPrinting extends Mock
String? subject,
String? body,
List<String>? emails,
) async => true;
) async =>
true;

@override
Future<Printer?> pickPrinter(Rect bounds) async => null;
Expand Down
Loading
Loading