PrintingPlugin.swift 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. import Flutter
  17. import Foundation
  18. @objc
  19. public class PrintingPlugin: NSObject, FlutterPlugin {
  20. private static var instance: PrintingPlugin?
  21. private var channel: FlutterMethodChannel
  22. public var jobs = [UInt32: PrintJob]()
  23. init(_ channel: FlutterMethodChannel) {
  24. self.channel = channel
  25. super.init()
  26. PrintingPlugin.instance = self
  27. }
  28. @objc
  29. public static func setDocument(job: UInt32, doc: UnsafePointer<UInt8>, size: UInt64) {
  30. instance!.jobs[job]?.setDocument(Data(bytes: doc, count: Int(size)))
  31. }
  32. @objc
  33. public static func setError(job: UInt32, message: UnsafePointer<CChar>) {
  34. instance!.jobs[job]?.cancelJob(String(cString: message))
  35. }
  36. /// Entry point
  37. public static func register(with registrar: FlutterPluginRegistrar) {
  38. let channel = FlutterMethodChannel(name: "net.nfet.printing", binaryMessenger: registrar.messenger())
  39. let instance = PrintingPlugin(channel)
  40. registrar.addMethodCallDelegate(instance, channel: channel)
  41. }
  42. /// Flutter method handlers
  43. public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
  44. let args = call.arguments! as! [String: Any]
  45. if call.method == "printPdf" {
  46. let name = args["name"] as! String
  47. let printer = args["printer"] as? String
  48. let width = CGFloat((args["width"] as! NSNumber).floatValue)
  49. let height = CGFloat((args["height"] as! NSNumber).floatValue)
  50. let marginLeft = CGFloat((args["marginLeft"] as! NSNumber).floatValue)
  51. let marginTop = CGFloat((args["marginTop"] as! NSNumber).floatValue)
  52. let marginRight = CGFloat((args["marginRight"] as! NSNumber).floatValue)
  53. let marginBottom = CGFloat((args["marginBottom"] as! NSNumber).floatValue)
  54. let printJob = PrintJob(printing: self, index: args["job"] as! Int)
  55. let dynamic = args["dynamic"] as! Bool
  56. jobs[args["job"] as! UInt32] = printJob
  57. printJob.printPdf(name: name,
  58. withPageSize: CGSize(
  59. width: width,
  60. height: height
  61. ),
  62. andMargin: CGRect(
  63. x: marginLeft,
  64. y: marginTop,
  65. width: width - marginRight - marginLeft,
  66. height: height - marginBottom - marginTop
  67. ), withPrinter: printer,
  68. dynamically: dynamic)
  69. result(NSNumber(value: 1))
  70. } else if call.method == "sharePdf" {
  71. let object = args["doc"] as! FlutterStandardTypedData
  72. PrintJob.sharePdf(
  73. data: object.data,
  74. withSourceRect: CGRect(
  75. x: CGFloat((args["x"] as? NSNumber)?.floatValue ?? 0.0),
  76. y: CGFloat((args["y"] as? NSNumber)?.floatValue ?? 0.0),
  77. width: CGFloat((args["w"] as? NSNumber)?.floatValue ?? 0.0),
  78. height: CGFloat((args["h"] as? NSNumber)?.floatValue ?? 0.0)
  79. ),
  80. andName: args["name"] as! String,
  81. subject: args["subject"] as? String,
  82. body: args["body"] as? String
  83. )
  84. result(NSNumber(value: 1))
  85. } else if call.method == "convertHtml" {
  86. let width = CGFloat((args["width"] as? NSNumber)?.floatValue ?? 0.0)
  87. let height = CGFloat((args["height"] as? NSNumber)?.floatValue ?? 0.0)
  88. let marginLeft = CGFloat((args["marginLeft"] as? NSNumber)?.floatValue ?? 0.0)
  89. let marginTop = CGFloat((args["marginTop"] as? NSNumber)?.floatValue ?? 0.0)
  90. let marginRight = CGFloat((args["marginRight"] as? NSNumber)?.floatValue ?? 0.0)
  91. let marginBottom = CGFloat((args["marginBottom"] as? NSNumber)?.floatValue ?? 0.0)
  92. let printJob = PrintJob(printing: self, index: args["job"] as! Int)
  93. printJob.convertHtml(
  94. args["html"] as! String,
  95. withPageSize: CGRect(
  96. x: 0.0,
  97. y: 0.0,
  98. width: width,
  99. height: height
  100. ),
  101. andMargin: CGRect(
  102. x: marginLeft,
  103. y: marginTop,
  104. width: width - marginRight - marginLeft,
  105. height: height - marginBottom - marginTop
  106. ),
  107. andBaseUrl: args["baseUrl"] as? String == nil ? nil : URL(string: args["baseUrl"] as! String)
  108. )
  109. result(NSNumber(value: 1))
  110. } else if call.method == "pickPrinter" {
  111. PrintJob.pickPrinter(result: result, withSourceRect: CGRect(
  112. x: CGFloat((args["x"] as? NSNumber)?.floatValue ?? 0.0),
  113. y: CGFloat((args["y"] as? NSNumber)?.floatValue ?? 0.0),
  114. width: CGFloat((args["w"] as? NSNumber)?.floatValue ?? 0.0),
  115. height: CGFloat((args["h"] as? NSNumber)?.floatValue ?? 0.0)
  116. ))
  117. } else if call.method == "printingInfo" {
  118. result(PrintJob.printingInfo())
  119. } else if call.method == "rasterPdf" {
  120. let doc = args["doc"] as! FlutterStandardTypedData
  121. let pages = args["pages"] as? [Int]
  122. let scale = CGFloat((args["scale"] as! NSNumber).floatValue)
  123. let printJob = PrintJob(printing: self, index: args["job"] as! Int)
  124. printJob.rasterPdf(data: doc.data,
  125. pages: pages,
  126. scale: scale)
  127. result(NSNumber(value: 1))
  128. } else {
  129. result(FlutterMethodNotImplemented)
  130. }
  131. }
  132. /// Request the Pdf document from flutter
  133. public func onLayout(printJob: PrintJob, width: CGFloat, height: CGFloat, marginLeft: CGFloat, marginTop: CGFloat, marginRight: CGFloat, marginBottom: CGFloat) {
  134. let arg = [
  135. "width": width,
  136. "height": height,
  137. "marginLeft": marginLeft,
  138. "marginTop": marginTop,
  139. "marginRight": marginRight,
  140. "marginBottom": marginBottom,
  141. "job": printJob.index,
  142. ] as [String: Any]
  143. channel.invokeMethod("onLayout", arguments: arg)
  144. }
  145. /// send completion status to flutter
  146. public func onCompleted(printJob: PrintJob, completed: Bool, error: NSString?) {
  147. let data: NSDictionary = [
  148. "completed": completed,
  149. "error": error as Any,
  150. "job": printJob.index,
  151. ]
  152. channel.invokeMethod("onCompleted", arguments: data)
  153. jobs.removeValue(forKey: UInt32(printJob.index))
  154. }
  155. /// send html to pdf data result to flutter
  156. public func onHtmlRendered(printJob: PrintJob, pdfData: Data) {
  157. let data: NSDictionary = [
  158. "doc": FlutterStandardTypedData(bytes: pdfData),
  159. "job": printJob.index,
  160. ]
  161. channel.invokeMethod("onHtmlRendered", arguments: data)
  162. }
  163. /// send html to pdf conversion error to flutter
  164. public func onHtmlError(printJob: PrintJob, error: String) {
  165. let data: NSDictionary = [
  166. "error": error,
  167. "job": printJob.index,
  168. ]
  169. channel.invokeMethod("onHtmlError", arguments: data)
  170. }
  171. /// send pdf to raster data result to flutter
  172. public func onPageRasterized(printJob: PrintJob, imageData: Data, width: Int, height: Int) {
  173. let data: NSDictionary = [
  174. "image": FlutterStandardTypedData(bytes: imageData),
  175. "width": width,
  176. "height": height,
  177. "job": printJob.index,
  178. ]
  179. channel.invokeMethod("onPageRasterized", arguments: data)
  180. }
  181. public func onPageRasterEnd(printJob: PrintJob, error: String?) {
  182. let data: NSDictionary = [
  183. "job": printJob.index,
  184. "error": error as Any,
  185. ]
  186. channel.invokeMethod("onPageRasterEnd", arguments: data)
  187. }
  188. }