Hasan
Committed by GitHub

fix: re-init UIPrinter cause issues with delegate (#1363)

* fix: re-init UIPrinter cause issues with delegate

* change selectedPrinters to map of URL:UIPrinter
@@ -21,6 +21,10 @@ func dataProviderReleaseDataCallback(info _: UnsafeMutableRawPointer?, data: Uns @@ -21,6 +21,10 @@ func dataProviderReleaseDataCallback(info _: UnsafeMutableRawPointer?, data: Uns
21 data.deallocate() 21 data.deallocate()
22 } 22 }
23 23
  24 +// A variable that holds the selected printers to prevent recreate it if selected again
  25 +// Each printer will be identified by its URL string
  26 +var selectedPrinters = [String: UIPrinter]()
  27 +
24 public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate { 28 public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate {
25 private var printing: PrintingPlugin 29 private var printing: PrintingPlugin
26 public var index: Int 30 public var index: Int
@@ -32,14 +36,14 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -32,14 +36,14 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
32 private let semaphore = DispatchSemaphore(value: 0) 36 private let semaphore = DispatchSemaphore(value: 0)
33 private var dynamic = false 37 private var dynamic = false
34 private var currentSize: CGSize? 38 private var currentSize: CGSize?
35 - 39 +
36 public init(printing: PrintingPlugin, index: Int) { 40 public init(printing: PrintingPlugin, index: Int) {
37 self.printing = printing 41 self.printing = printing
38 self.index = index 42 self.index = index
39 pdfDocument = nil 43 pdfDocument = nil
40 super.init() 44 super.init()
41 } 45 }
42 - 46 +
43 override public func drawPage(at pageIndex: Int, in _: CGRect) { 47 override public func drawPage(at pageIndex: Int, in _: CGRect) {
44 let ctx = UIGraphicsGetCurrentContext() 48 let ctx = UIGraphicsGetCurrentContext()
45 let page = pdfDocument?.page(at: pageIndex + 1) 49 let page = pdfDocument?.page(at: pageIndex + 1)
@@ -49,7 +53,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -49,7 +53,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
49 ctx?.drawPDFPage(page!) 53 ctx?.drawPDFPage(page!)
50 } 54 }
51 } 55 }
52 - 56 +
53 func cancelJob(_ error: String?) { 57 func cancelJob(_ error: String?) {
54 pdfDocument = nil 58 pdfDocument = nil
55 if dynamic { 59 if dynamic {
@@ -58,23 +62,23 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -58,23 +62,23 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
58 printing.onCompleted(printJob: self, completed: false, error: error as NSString?) 62 printing.onCompleted(printJob: self, completed: false, error: error as NSString?)
59 } 63 }
60 } 64 }
61 - 65 +
62 func setDocument(_ data: Data?) { 66 func setDocument(_ data: Data?) {
63 let bytesPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: data?.count ?? 0) 67 let bytesPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: data?.count ?? 0)
64 data?.copyBytes(to: bytesPointer, count: data?.count ?? 0) 68 data?.copyBytes(to: bytesPointer, count: data?.count ?? 0)
65 let dataProvider = CGDataProvider(dataInfo: nil, data: bytesPointer, size: data?.count ?? 0, releaseData: dataProviderReleaseDataCallback) 69 let dataProvider = CGDataProvider(dataInfo: nil, data: bytesPointer, size: data?.count ?? 0, releaseData: dataProviderReleaseDataCallback)
66 pdfDocument = CGPDFDocument(dataProvider!) 70 pdfDocument = CGPDFDocument(dataProvider!)
67 - 71 +
68 if dynamic { 72 if dynamic {
69 // Unblock the main thread 73 // Unblock the main thread
70 semaphore.signal() 74 semaphore.signal()
71 return 75 return
72 } 76 }
73 - 77 +
74 DispatchQueue.main.async { [self] in 78 DispatchQueue.main.async { [self] in
75 let controller = UIPrintInteractionController.shared 79 let controller = UIPrintInteractionController.shared
76 controller.delegate = self 80 controller.delegate = self
77 - 81 +
78 let printInfo = UIPrintInfo.printInfo() 82 let printInfo = UIPrintInfo.printInfo()
79 printInfo.jobName = jobName! 83 printInfo.jobName = jobName!
80 printInfo.outputType = .general 84 printInfo.outputType = .general
@@ -84,30 +88,35 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -84,30 +88,35 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
84 } 88 }
85 controller.printInfo = printInfo 89 controller.printInfo = printInfo
86 controller.printPageRenderer = self 90 controller.printPageRenderer = self
87 - 91 +
88 if self.printerName != nil { 92 if self.printerName != nil {
89 let printerURL = URL(string: self.printerName!) 93 let printerURL = URL(string: self.printerName!)
90 - 94 +
91 if printerURL == nil { 95 if printerURL == nil {
92 self.printing.onCompleted(printJob: self, completed: false, error: "Unable to find printer URL") 96 self.printing.onCompleted(printJob: self, completed: false, error: "Unable to find printer URL")
93 return 97 return
94 } 98 }
95 -  
96 - let printer = UIPrinter(url: printerURL!)  
97 - printer.contactPrinter { available in 99 +
  100 + let printerURLString = printerURL!.absoluteString
  101 +
  102 + if !selectedPrinters.keys.contains(printerURLString) {
  103 + selectedPrinters[printerURLString] = UIPrinter(url: printerURL!)
  104 + }
  105 +
  106 + selectedPrinters[printerURLString]!.contactPrinter { available in
98 if !available { 107 if !available {
99 self.printing.onCompleted(printJob: self, completed: false, error: "Printer not available") 108 self.printing.onCompleted(printJob: self, completed: false, error: "Printer not available")
100 return 109 return
101 } 110 }
102 -  
103 - controller.print(to: printer, completionHandler: self.completionHandler) 111 +
  112 + controller.print(to: selectedPrinters[printerURLString]!, completionHandler: self.completionHandler)
104 } 113 }
105 } else { 114 } else {
106 controller.present(animated: true, completionHandler: self.completionHandler) 115 controller.present(animated: true, completionHandler: self.completionHandler)
107 } 116 }
108 } 117 }
109 } 118 }
110 - 119 +
111 override public var numberOfPages: Int { 120 override public var numberOfPages: Int {
112 if dynamic { 121 if dynamic {
113 printing.onLayout( 122 printing.onLayout(
@@ -119,19 +128,19 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -119,19 +128,19 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
119 marginRight: paperRect.size.width - (printableRect.origin.x + printableRect.size.width), 128 marginRight: paperRect.size.width - (printableRect.origin.x + printableRect.size.width),
120 marginBottom: paperRect.size.height - (printableRect.origin.y + printableRect.size.height) 129 marginBottom: paperRect.size.height - (printableRect.origin.y + printableRect.size.height)
121 ) 130 )
122 - 131 +
123 // Block the main thread, waiting for a document 132 // Block the main thread, waiting for a document
124 semaphore.wait() 133 semaphore.wait()
125 } 134 }
126 - 135 +
127 return pdfDocument?.numberOfPages ?? 0 136 return pdfDocument?.numberOfPages ?? 0
128 } 137 }
129 - 138 +
130 func completionHandler(printController _: UIPrintInteractionController, completed: Bool, error: Error?) { 139 func completionHandler(printController _: UIPrintInteractionController, completed: Bool, error: Error?) {
131 if !completed, error != nil { 140 if !completed, error != nil {
132 print("Unable to print: \(error?.localizedDescription ?? "unknown error")") 141 print("Unable to print: \(error?.localizedDescription ?? "unknown error")")
133 } 142 }
134 - 143 +
135 printing.onCompleted(printJob: self, completed: completed, error: error?.localizedDescription as NSString?) 144 printing.onCompleted(printJob: self, completed: completed, error: error?.localizedDescription as NSString?)
136 } 145 }
137 146
@@ -144,7 +153,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -144,7 +153,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
144 153
145 return bestPaper 154 return bestPaper
146 } 155 }
147 - 156 +
148 func printPdf(name: String, withPageSize size: CGSize, andMargin margin: CGRect, withPrinter printerID: String?, dynamically dyn: Bool) { 157 func printPdf(name: String, withPageSize size: CGSize, andMargin margin: CGRect, withPrinter printerID: String?, dynamically dyn: Bool) {
149 currentSize = size 158 currentSize = size
150 dynamic = dyn 159 dynamic = dyn
@@ -153,17 +162,17 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -153,17 +162,17 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
153 self.printing.onCompleted(printJob: self, completed: false, error: "Printing not available") 162 self.printing.onCompleted(printJob: self, completed: false, error: "Printing not available")
154 return 163 return
155 } 164 }
156 - 165 +
157 if size.width > size.height { 166 if size.width > size.height {
158 orientation = UIPrintInfo.Orientation.landscape 167 orientation = UIPrintInfo.Orientation.landscape
159 } 168 }
160 - 169 +
161 jobName = name 170 jobName = name
162 printerName = printerID 171 printerName = printerID
163 - 172 +
164 let controller = UIPrintInteractionController.shared 173 let controller = UIPrintInteractionController.shared
165 controller.delegate = self 174 controller.delegate = self
166 - 175 +
167 let printInfo = UIPrintInfo.printInfo() 176 let printInfo = UIPrintInfo.printInfo()
168 printInfo.jobName = jobName! 177 printInfo.jobName = jobName!
169 printInfo.outputType = .general 178 printInfo.outputType = .general
@@ -173,27 +182,40 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -173,27 +182,40 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
173 } 182 }
174 controller.printInfo = printInfo 183 controller.printInfo = printInfo
175 controller.showsPaperSelectionForLoadedPapers = true 184 controller.showsPaperSelectionForLoadedPapers = true
176 - 185 +
177 controller.printPageRenderer = self 186 controller.printPageRenderer = self
178 - 187 +
179 if printerID != nil { 188 if printerID != nil {
180 let printerURL = URL(string: printerID!) 189 let printerURL = URL(string: printerID!)
181 - 190 +
182 if printerURL == nil { 191 if printerURL == nil {
183 self.printing.onCompleted(printJob: self, completed: false, error: "Unable to find printer URL") 192 self.printing.onCompleted(printJob: self, completed: false, error: "Unable to find printer URL")
184 return 193 return
185 } 194 }
186 -  
187 - let printer = UIPrinter(url: printerURL!)  
188 - controller.print(to: printer, completionHandler: completionHandler) 195 +
  196 + let printerURLString = printerURL!.absoluteString
  197 +
  198 + if !selectedPrinters.keys.contains(printerURLString) {
  199 + selectedPrinters[printerURLString] = UIPrinter(url: printerURL!)
  200 + }
  201 +
  202 +
  203 + selectedPrinters[printerURLString]!.contactPrinter { available in
  204 + if !available {
  205 + self.printing.onCompleted(printJob: self, completed: false, error: "Printer not available")
  206 + return
  207 + }
  208 +
  209 + controller.print(to: selectedPrinters[printerURLString]!, completionHandler: self.completionHandler)
  210 + }
189 return 211 return
190 } 212 }
191 - 213 +
192 if dynamic { 214 if dynamic {
193 controller.present(animated: true, completionHandler: completionHandler) 215 controller.present(animated: true, completionHandler: completionHandler)
194 return 216 return
195 } 217 }
196 - 218 +
197 self.printing.onLayout( 219 self.printing.onLayout(
198 printJob: self, 220 printJob: self,
199 width: size.width, 221 width: size.width,
@@ -204,18 +226,18 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -204,18 +226,18 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
204 marginBottom: size.height - margin.maxY 226 marginBottom: size.height - margin.maxY
205 ) 227 )
206 } 228 }
207 - 229 +
208 static func sharePdf(data: Data, withSourceRect rect: CGRect, andName name: String, subject: String?, body: String?) { 230 static func sharePdf(data: Data, withSourceRect rect: CGRect, andName name: String, subject: String?, body: String?) {
209 let tmpDirURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true) 231 let tmpDirURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
210 let fileURL = tmpDirURL.appendingPathComponent(name) 232 let fileURL = tmpDirURL.appendingPathComponent(name)
211 - 233 +
212 do { 234 do {
213 try data.write(to: fileURL, options: .atomic) 235 try data.write(to: fileURL, options: .atomic)
214 } catch { 236 } catch {
215 print("sharePdf error: \(error.localizedDescription)") 237 print("sharePdf error: \(error.localizedDescription)")
216 return 238 return
217 } 239 }
218 - 240 +
219 let activityViewController = UIActivityViewController(activityItems: [fileURL, body as Any], applicationActivities: nil) 241 let activityViewController = UIActivityViewController(activityItems: [fileURL, body as Any], applicationActivities: nil)
220 activityViewController.setValue(subject, forKey: "subject") 242 activityViewController.setValue(subject, forKey: "subject")
221 if UIDevice.current.userInterfaceIdiom == .pad { 243 if UIDevice.current.userInterfaceIdiom == .pad {
@@ -225,7 +247,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -225,7 +247,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
225 } 247 }
226 UIApplication.shared.keyWindow?.rootViewController?.present(activityViewController, animated: true) 248 UIApplication.shared.keyWindow?.rootViewController?.present(activityViewController, animated: true)
227 } 249 }
228 - 250 +
229 func convertHtml(_ data: String, withPageSize rect: CGRect, andMargin margin: CGRect, andBaseUrl baseUrl: URL?) { 251 func convertHtml(_ data: String, withPageSize rect: CGRect, andMargin margin: CGRect, andBaseUrl baseUrl: URL?) {
230 let viewController = UIApplication.shared.delegate?.window?!.rootViewController 252 let viewController = UIApplication.shared.delegate?.window?!.rootViewController
231 let wkWebView = WKWebView(frame: viewController!.view.bounds) 253 let wkWebView = WKWebView(frame: viewController!.view.bounds)
@@ -233,32 +255,32 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -233,32 +255,32 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
233 wkWebView.tag = 100 255 wkWebView.tag = 100
234 viewController?.view.addSubview(wkWebView) 256 viewController?.view.addSubview(wkWebView)
235 wkWebView.loadHTMLString(data, baseURL: baseUrl ?? Bundle.main.bundleURL) 257 wkWebView.loadHTMLString(data, baseURL: baseUrl ?? Bundle.main.bundleURL)
236 - 258 +
237 urlObservation = wkWebView.observe(\.isLoading, changeHandler: { _, _ in 259 urlObservation = wkWebView.observe(\.isLoading, changeHandler: { _, _ in
238 // this is workaround for issue with loading local images 260 // this is workaround for issue with loading local images
239 DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { 261 DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
240 // assign the print formatter to the print page renderer 262 // assign the print formatter to the print page renderer
241 let renderer = UIPrintPageRenderer() 263 let renderer = UIPrintPageRenderer()
242 renderer.addPrintFormatter(wkWebView.viewPrintFormatter(), startingAtPageAt: 0) 264 renderer.addPrintFormatter(wkWebView.viewPrintFormatter(), startingAtPageAt: 0)
243 - 265 +
244 // assign paperRect and printableRect values 266 // assign paperRect and printableRect values
245 renderer.setValue(rect, forKey: "paperRect") 267 renderer.setValue(rect, forKey: "paperRect")
246 renderer.setValue(margin, forKey: "printableRect") 268 renderer.setValue(margin, forKey: "printableRect")
247 - 269 +
248 // create pdf context and draw each page 270 // create pdf context and draw each page
249 let pdfData = NSMutableData() 271 let pdfData = NSMutableData()
250 UIGraphicsBeginPDFContextToData(pdfData, rect, nil) 272 UIGraphicsBeginPDFContextToData(pdfData, rect, nil)
251 - 273 +
252 for i in 0 ..< renderer.numberOfPages { 274 for i in 0 ..< renderer.numberOfPages {
253 UIGraphicsBeginPDFPage() 275 UIGraphicsBeginPDFPage()
254 renderer.drawPage(at: i, in: UIGraphicsGetPDFContextBounds()) 276 renderer.drawPage(at: i, in: UIGraphicsGetPDFContextBounds())
255 } 277 }
256 - 278 +
257 UIGraphicsEndPDFContext() 279 UIGraphicsEndPDFContext()
258 - 280 +
259 if let viewWithTag = viewController?.view.viewWithTag(wkWebView.tag) { 281 if let viewWithTag = viewController?.view.viewWithTag(wkWebView.tag) {
260 viewWithTag.removeFromSuperview() // remove hidden webview when pdf is generated 282 viewWithTag.removeFromSuperview() // remove hidden webview when pdf is generated
261 - 283 +
262 // clear WKWebView cache 284 // clear WKWebView cache
263 if #available(iOS 9.0, *) { 285 if #available(iOS 9.0, *) {
264 WKWebsiteDataStore.default().fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) { records in 286 WKWebsiteDataStore.default().fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) { records in
@@ -268,40 +290,40 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -268,40 +290,40 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
268 } 290 }
269 } 291 }
270 } 292 }
271 - 293 +
272 // dispose urlObservation 294 // dispose urlObservation
273 self.urlObservation = nil 295 self.urlObservation = nil
274 self.printing.onHtmlRendered(printJob: self, pdfData: pdfData as Data) 296 self.printing.onHtmlRendered(printJob: self, pdfData: pdfData as Data)
275 } 297 }
276 }) 298 })
277 } 299 }
278 - 300 +
279 static func pickPrinter(result: @escaping FlutterResult, withSourceRect rect: CGRect) { 301 static func pickPrinter(result: @escaping FlutterResult, withSourceRect rect: CGRect) {
280 let controller = UIPrinterPickerController(initiallySelectedPrinter: nil) 302 let controller = UIPrinterPickerController(initiallySelectedPrinter: nil)
281 - 303 +
282 let pickPrinterCompletionHandler: UIPrinterPickerController.CompletionHandler = { 304 let pickPrinterCompletionHandler: UIPrinterPickerController.CompletionHandler = {
283 (printerPickerController: UIPrinterPickerController, completed: Bool, error: Error?) in 305 (printerPickerController: UIPrinterPickerController, completed: Bool, error: Error?) in
284 - if !completed, error != nil {  
285 - print("Unable to pick printer: \(error?.localizedDescription ?? "unknown error")")  
286 - result(nil)  
287 - return  
288 - }  
289 -  
290 - if printerPickerController.selectedPrinter == nil {  
291 - result(nil)  
292 - return  
293 - }  
294 -  
295 - let printer = printerPickerController.selectedPrinter!  
296 - let data: NSDictionary = [  
297 - "url": printer.url.absoluteString as Any,  
298 - "name": printer.displayName as Any,  
299 - "model": printer.makeAndModel as Any,  
300 - "location": printer.displayLocation as Any,  
301 - ]  
302 - result(data) 306 + if !completed, error != nil {
  307 + print("Unable to pick printer: \(error?.localizedDescription ?? "unknown error")")
  308 + result(nil)
  309 + return
  310 + }
  311 +
  312 + if printerPickerController.selectedPrinter == nil {
  313 + result(nil)
  314 + return
  315 + }
  316 +
  317 + let printer = printerPickerController.selectedPrinter!
  318 + let data: NSDictionary = [
  319 + "url": printer.url.absoluteString as Any,
  320 + "name": printer.displayName as Any,
  321 + "model": printer.makeAndModel as Any,
  322 + "location": printer.displayLocation as Any,
  323 + ]
  324 + result(data)
303 } 325 }
304 - 326 +
305 if UIDevice.current.userInterfaceIdiom == .pad { 327 if UIDevice.current.userInterfaceIdiom == .pad {
306 let viewController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController 328 let viewController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController
307 if viewController != nil { 329 if viewController != nil {
@@ -309,10 +331,10 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -309,10 +331,10 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
309 return 331 return
310 } 332 }
311 } 333 }
312 - 334 +
313 controller.present(animated: true, completionHandler: pickPrinterCompletionHandler) 335 controller.present(animated: true, completionHandler: pickPrinterCompletionHandler)
314 } 336 }
315 - 337 +
316 public func rasterPdf(data: Data, pages: [Int]?, scale: CGFloat) { 338 public func rasterPdf(data: Data, pages: [Int]?, scale: CGFloat) {
317 guard 339 guard
318 let provider = CGDataProvider(data: data as CFData), 340 let provider = CGDataProvider(data: data as CFData),
@@ -321,10 +343,10 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -321,10 +343,10 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
321 printing.onPageRasterEnd(printJob: self, error: "Cannot raster a malformed PDF file") 343 printing.onPageRasterEnd(printJob: self, error: "Cannot raster a malformed PDF file")
322 return 344 return
323 } 345 }
324 - 346 +
325 DispatchQueue.global().async { 347 DispatchQueue.global().async {
326 let pageCount = document.numberOfPages 348 let pageCount = document.numberOfPages
327 - 349 +
328 for pageNum in pages ?? Array(0 ... pageCount - 1) { 350 for pageNum in pages ?? Array(0 ... pageCount - 1) {
329 guard let page = document.page(at: pageNum + 1) else { continue } 351 guard let page = document.page(at: pageNum + 1) else { continue }
330 let angle = CGFloat(page.rotationAngle) * CGFloat.pi / -180 352 let angle = CGFloat(page.rotationAngle) * CGFloat.pi / -180
@@ -333,7 +355,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -333,7 +355,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
333 let height = Int(abs((cos(angle) * rect.height + sin(angle) * rect.width) * scale)) 355 let height = Int(abs((cos(angle) * rect.height + sin(angle) * rect.width) * scale))
334 let stride = width * 4 356 let stride = width * 4
335 var data = Data(repeating: 0, count: stride * height) 357 var data = Data(repeating: 0, count: stride * height)
336 - 358 +
337 data.withUnsafeMutableBytes { (outputBytes: UnsafeMutableRawBufferPointer) in 359 data.withUnsafeMutableBytes { (outputBytes: UnsafeMutableRawBufferPointer) in
338 let rgb = CGColorSpaceCreateDeviceRGB() 360 let rgb = CGColorSpaceCreateDeviceRGB()
339 let context = CGContext( 361 let context = CGContext(
@@ -345,7 +367,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -345,7 +367,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
345 space: rgb, 367 space: rgb,
346 bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue 368 bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue
347 ) 369 )
348 - 370 +
349 if context != nil { 371 if context != nil {
350 context!.translateBy(x: CGFloat(width) / 2, y: CGFloat(height) / 2) 372 context!.translateBy(x: CGFloat(width) / 2, y: CGFloat(height) / 2)
351 context!.scaleBy(x: scale, y: scale) 373 context!.scaleBy(x: scale, y: scale)
@@ -354,18 +376,18 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate @@ -354,18 +376,18 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate
354 context!.drawPDFPage(page) 376 context!.drawPDFPage(page)
355 } 377 }
356 } 378 }
357 - 379 +
358 DispatchQueue.main.sync { 380 DispatchQueue.main.sync {
359 self.printing.onPageRasterized(printJob: self, imageData: data, width: width, height: height) 381 self.printing.onPageRasterized(printJob: self, imageData: data, width: width, height: height)
360 } 382 }
361 } 383 }
362 - 384 +
363 DispatchQueue.main.sync { 385 DispatchQueue.main.sync {
364 self.printing.onPageRasterEnd(printJob: self, error: nil) 386 self.printing.onPageRasterEnd(printJob: self, error: nil)
365 } 387 }
366 } 388 }
367 } 389 }
368 - 390 +
369 public static func printingInfo() -> NSDictionary { 391 public static func printingInfo() -> NSDictionary {
370 let data: NSDictionary = [ 392 let data: NSDictionary = [
371 "directPrint": true, 393 "directPrint": true,