KMPrintPresenter.swift 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  1. //
  2. // KMPrintPresenter.swift
  3. // PDF Master
  4. //
  5. // Created by lizhe on 2022/12/21.
  6. //
  7. import Cocoa
  8. import PDFKit
  9. //MARK: CPDFKit page 方法无法使用 暂时使用系统方法
  10. class KMPrintPresenter: NSObject {
  11. lazy var printData: KMPrintModel! = KMPrintModel()
  12. var document: CPDFDocument?
  13. fileprivate weak var delegate: KMPrintPresenterDeleage?
  14. /**
  15. 初始化presenter 绑定数据
  16. */
  17. func initPresenter(delegate: KMPrintPresenterDeleage, data: KMPrintModel, document: CPDFDocument) {
  18. self.delegate = delegate
  19. self.printData = data
  20. self.document = document
  21. self.updatePrintDocument(documentURL: document.documentURL, data: self.printData)
  22. }
  23. /**
  24. 刷新数据
  25. */
  26. func reloadData() {
  27. self.updatePrintDocument(documentURL: self.document!.documentURL, data: self.printData)
  28. }
  29. /**
  30. @abstract 解除绑定
  31. */
  32. func free() {
  33. delegate = nil
  34. }
  35. }
  36. protocol KMPrintPresenterDeleage: NSObject {
  37. func showData(presenter: KMPrintPresenter, document: CPDFDocument)
  38. }
  39. protocol KMPrintPresenterDocument: NSObject {}
  40. extension KMPrintPresenter: KMPrintPresenterDocument {
  41. /**
  42. @abstract 获取打印document
  43. @param url 源文件url
  44. @param data 数据
  45. @retrun document
  46. */
  47. func updatePrintDocument(documentURL: URL, data: KMPrintModel) -> CPDFDocument {
  48. // 获取基本参数
  49. let printModel: KMPrintModel = data
  50. //获取总page
  51. let pages = self.fetchPages(documentURL, printModel.page)
  52. //绘制PDF
  53. let filePath = self.drawPages(nil, printModel, pages)
  54. let result = CPDFDocument(url: URL(fileURLWithPath: filePath))!
  55. if self.delegate != nil {
  56. self.delegate?.showData(presenter: self, document: result)
  57. }
  58. KMPrint("保存地址" + filePath)
  59. return result
  60. }
  61. /**
  62. @abstract 插入page
  63. @param paperSet 纸张设置
  64. @param pageSet page设置
  65. @param pages page数组
  66. */
  67. func drawPages(_ toFilePath: String?,
  68. _ printModel: KMPrintModel,
  69. _ pages: [KMPrintDrawPage]) -> String {
  70. /**
  71. 参数
  72. */
  73. //纸张大小
  74. let paperSize: CGSize = self.fetchPaperSize(printModel.paper)
  75. //总页数
  76. let paperCount: Int = self.fetchTotalPaperCount(paperSize, pages, printModel.page)
  77. //每页page数
  78. let pageOfPaperCount: Int = self.fetchPageOfPaper(printModel.page)
  79. //获取每张纸的page
  80. let drawPages: [[KMPrintDrawPage]] = self.fetchDrawPages(paperSize, printModel.page, paperCount, pageOfPaperCount, pages)
  81. //导出地址
  82. let filePath = KMPrintPresenter.fetchSaveFilePath(toFilePath)
  83. /**
  84. 绘制每张纸的内容
  85. */
  86. //创建画布
  87. let context: CGContext = self.createContext(filePath, paperSize)
  88. for drawPage in drawPages {
  89. context.beginPDFPage(nil)
  90. self.drawPageToContext(context, drawPage, printModel)
  91. context.endPDFPage()
  92. }
  93. context.closePDF()
  94. return filePath
  95. }
  96. /**
  97. 获取绘制的pages
  98. @pageModel page参数
  99. @param paperCount 纸张数量
  100. @param pageOfPaperCount 每张纸的page数量
  101. @param pages 所有page数量
  102. */
  103. func fetchDrawPages(_ paperSize: CGSize, _ pageModel: KMPrintPageModel,_ paperCount: Int, _ pageOfPaperCount: Int, _ pages: [KMPrintDrawPage]) -> [[KMPrintDrawPage]] {
  104. guard pages.count != 0 else {
  105. return []
  106. }
  107. //一个page重复获取次数
  108. var pageRepetitionCount = 1
  109. if (pageModel.operation.type == .poster) {
  110. if (pageModel.operation.poster.type == .tile) {
  111. pageRepetitionCount = Int(pageModel.operation.poster.tilePoint.x * pageModel.operation.poster.tilePoint.y)
  112. } else if (pageModel.operation.poster.type == .breakUp) {
  113. pageRepetitionCount = Int(pageModel.operation.poster.pageOfPaper.point.x * pageModel.operation.poster.pageOfPaper.point.y)
  114. }
  115. }
  116. var drawPages:[[KMPrintDrawPage]] = []
  117. for i in 0...(paperCount - 1) {
  118. //获取多页page
  119. var tempPags: [KMPrintDrawPage] = []
  120. for j in 0...(pageOfPaperCount - 1) {
  121. let pageIndex = i / pageRepetitionCount
  122. if (pageIndex * pageOfPaperCount + j < pages.count) {
  123. let originDrawPage = (pages[pageIndex * pageOfPaperCount + j])
  124. let drawPage = KMPrintDrawPage()
  125. drawPage.page = originDrawPage.page
  126. var pageCropRect = self.fetchPageCropRect(paperSize,i % pageRepetitionCount, pageModel, drawPage)
  127. var pageShowRect = pageCropRect
  128. if (pageModel.operation.type == .poster) {
  129. if (pageModel.operation.poster.type == .tile) {
  130. pageShowRect = self.fetchPageShowRect(paperSize, i % pageRepetitionCount, pageModel, drawPage)
  131. } else if (pageModel.operation.poster.type == .breakUp) {
  132. pageShowRect = pageCropRect
  133. }
  134. }
  135. drawPage.cropRect = pageCropRect
  136. drawPage.showRect = pageShowRect
  137. tempPags.append(drawPage)
  138. }
  139. }
  140. drawPages.append(tempPags)
  141. }
  142. return drawPages
  143. }
  144. /**
  145. 获取pages
  146. @param type 页面类型
  147. @param contentType annoation类型
  148. @param selectPages 当type 为custom时 传入选中page的下标
  149. */
  150. static func fetchSaveFilePath(_ filePath: String?) -> String {
  151. var saveFilePath = filePath ?? ""
  152. if saveFilePath.count == 0 {
  153. saveFilePath = NSTemporaryDirectory() + "/PDFMasterTest/test2.pdf"
  154. }
  155. if !FileManager.default.fileExists(atPath: NSTemporaryDirectory() + "/PDFMasterTest") {
  156. try?FileManager.default.createDirectory(atPath: NSTemporaryDirectory() + "/PDFMasterTest", withIntermediateDirectories: true)
  157. }
  158. if FileManager.default.fileExists(atPath: saveFilePath) {
  159. try?FileManager.default.removeItem(atPath: saveFilePath)
  160. }
  161. return saveFilePath
  162. }
  163. /**
  164. 获取pages
  165. @param type 页面类型
  166. @param contentType annoation类型
  167. @param selectPages 当type 为custom时 传入选中page的下标
  168. */
  169. static func creatDocument(_ url: URL) -> CPDFDocument {
  170. if FileManager.default.fileExists(atPath: NSTemporaryDirectory() + "/PDFMasterTest") {
  171. try?FileManager.default.createDirectory(atPath: NSTemporaryDirectory() + "/PDFMasterTest", withIntermediateDirectories: true)
  172. }
  173. let document = CPDFDocument(url: url)!
  174. // document.importPages(IndexSet(integer: 0), from: document, at: 0)
  175. let count = document.pageCount
  176. for _ in 0...(count - 1) {
  177. document.removePage(at: 0)
  178. }
  179. return document
  180. }
  181. /**
  182. 获取pages
  183. @param type 页面类型
  184. @param contentType annoation类型
  185. @param selectPages 当type 为custom时 传入选中page的下标
  186. */
  187. func fetchPages(_ documentURL: URL, _ pageModel: KMPrintPageModel) -> [KMPrintDrawPage] {
  188. let document = PDFDocument.init(url: documentURL)!
  189. var pageIndexs: [Int] = []
  190. let range = pageModel.range
  191. let contentType = pageModel.contentType
  192. let reversePrintOrder = range.reversePrintOrder
  193. switch range.type {
  194. case .allPage:
  195. for index in 0...document.pageCount - 1 {
  196. pageIndexs.append(index)
  197. }
  198. case .evenPage:
  199. for index in 0...document.pageCount - 1 {
  200. if index % 2 == 0 {
  201. pageIndexs.append(index)
  202. }
  203. }
  204. case .oddPage:
  205. for index in 0...document.pageCount - 1 {
  206. if index % 2 != 0 {
  207. pageIndexs.append(index)
  208. }
  209. }
  210. case .currentPage:
  211. pageIndexs.append(0)
  212. case .custom:
  213. pageIndexs.append(0)
  214. default:
  215. pageIndexs.append(0)
  216. }
  217. var pagesArray: [KMPrintDrawPage] = []
  218. for index in pageIndexs {
  219. let page = document.page(at: index)!
  220. let drawPage = KMPrintDrawPage()
  221. drawPage.page = page
  222. self.dealPageContent(contentType, [drawPage])
  223. if reversePrintOrder {
  224. pagesArray.insert(drawPage, at: 0)
  225. } else {
  226. pagesArray.append(drawPage)
  227. }
  228. }
  229. return pagesArray
  230. }
  231. /**
  232. 处理page annoation 内容
  233. @param contentType annoation类型
  234. @param pages page
  235. */
  236. func dealPageContent (_ contentType: KMPrintContentType, _ pages: [KMPrintDrawPage]) -> Void {
  237. for page in pages {
  238. let annoations: [PDFAnnotation] = page.page.annotations
  239. //内容处理
  240. switch contentType {
  241. case .document:
  242. for annoation in annoations {
  243. annoation.page!.removeAnnotation(annoation)
  244. }
  245. case .documentAndStamp:
  246. for annoation in annoations {
  247. if !self.isAnnoationStamp(type: annoation.type!) {
  248. annoation.page!.removeAnnotation(annoation)
  249. }
  250. }
  251. case .documentAndMarkup:
  252. for annoation in annoations {
  253. if !self.isAnnoationMarkup(type: annoation.type!) {
  254. annoation.page!.removeAnnotation(annoation)
  255. }
  256. }
  257. case .documentAndForm:
  258. for annoation in annoations {
  259. if !self.isAnnoationForm(type: annoation.type!) {
  260. annoation.page!.removeAnnotation(annoation)
  261. }
  262. }
  263. default:
  264. KMPrint("未找到")
  265. break
  266. }
  267. }
  268. }
  269. /**
  270. @abstract 获取context
  271. @param size纸张大小
  272. */
  273. func createContext(_ saveFilePath: String, _ size: CGSize) -> CGContext {
  274. var mediaBox: CGRect = NSMakeRect(0, 0, size.width, size.height)
  275. let url = CFURLCreateWithFileSystemPath(nil, saveFilePath as CFString, .cfurlposixPathStyle, false)
  276. let content: CGContext = CGContext.init(url!, mediaBox: &mediaBox, nil)!
  277. return content
  278. }
  279. /**
  280. @abstract 绘制page
  281. @param context
  282. @pages page数组 [CPDFPage]
  283. */
  284. func drawPageToContext(_ context: CGContext, _ pages: [KMPrintDrawPage], _ data: KMPrintModel, _ drawPageRect: CGRect = NSZeroRect) {
  285. //左下角有坐标系原点
  286. /**
  287. paper
  288. */
  289. let paperSize: CGSize = self.fetchPaperSize(data.paper)//纸张大小
  290. let paperItemSize: CGSize = self.fetchPaperItemSize(data.paper) //页面paper大小(去除边框)
  291. let paperInset: NSEdgeInsets = data.paper.info.inset //绘制paper大小
  292. let border: Bool = true //是否存在边框
  293. /**
  294. page
  295. */
  296. let pageOrder: KMPrintPageOperation.Multipage.Order = .horizontal //页面顺序
  297. let pageSize: CGSize = self.fetchPageItemSize(data.page, paperItemSize) //page大小
  298. let showModel: KMPrintPageOperation.Size = self.fetchShowModel(data.page)
  299. let autoRotate = self.fetchAutoRotate(data.page)
  300. let autoSize: Bool = self.fetchAutoSize(data.page)
  301. //行列
  302. let columnAndRow = self.fetchPageColumnAndRow(data.page) //行 列数量
  303. let columnAndRowSpace = CGPoint(x: 2, y: 2) //行 列之间的空间
  304. for i in 0...Int(columnAndRow.x) - 1 {
  305. for j in 0...(Int(columnAndRow.y) - 1) {
  306. let index = j + i * Int(columnAndRow.x)
  307. if index < pages.count {
  308. //参数
  309. let page: KMPrintDrawPage = pages[index]
  310. let rect = page.showRect
  311. //裁剪当前Page
  312. page.page.setBounds(page.cropRect, for: .cropBox)
  313. let pageItemSize = rect.size
  314. let rotate = page.page.rotation
  315. var scale = self.fetchPageScale(page, pageSize, autoRotate, autoSize)
  316. if data.page.operation.type == .size {
  317. if showModel.model == .custom {
  318. scale *= showModel.scale
  319. } else if showModel.model == .full {
  320. scale = 1
  321. }
  322. } else if (data.page.operation.type == .poster) {
  323. if (data.page.operation.poster.type == .tile) {
  324. scale = data.page.operation.poster.scale
  325. }
  326. }
  327. //当前item的自身中心点
  328. let center = CGPoint(x: (pageSize.width - pageItemSize.width * scale) / 2.0 ,
  329. y: (pageSize.height - pageItemSize.height * scale) / 2.0)
  330. var origin = rect.origin
  331. //多页Page自动旋转
  332. if autoSize {
  333. switch pageOrder {
  334. case .horizontal:
  335. origin.x = (pageSize.width + columnAndRowSpace.x) * CGFloat(j) + paperInset.left + center.x
  336. //页面内容高度 + 下边的行间距 - 第几个cell的高度 +居中
  337. origin.y = paperSize.height - (pageSize.height + columnAndRowSpace.y) * (CGFloat(i) + 1) + center.y + columnAndRowSpace.y
  338. case .horizontalReverseSequence:
  339. origin.x = paperSize.width - (pageSize.width + columnAndRowSpace.x) * (CGFloat(j) + 1) + center.x + columnAndRowSpace.x
  340. origin.y = paperSize.height - (pageSize.height + columnAndRowSpace.y) * (CGFloat(i) + 1) + center.y + paperInset.bottom + columnAndRowSpace.y
  341. case .vertical:
  342. origin.x = (pageSize.width + columnAndRowSpace.x) * CGFloat(i) + paperInset.left + center.x
  343. origin.y = paperSize.height - (pageSize.height + columnAndRowSpace.y) * (CGFloat(j) + 1) + center.y + paperInset.bottom + columnAndRowSpace.y
  344. case .verticalReverseSequence:
  345. origin.x = paperSize.width - (pageSize.width + columnAndRowSpace.x) * (CGFloat(i) + 1) + center.x + columnAndRowSpace.x
  346. origin.y = paperSize.height - (pageSize.height + columnAndRowSpace.y) * (CGFloat(j) + 1) + center.y + paperInset.bottom + columnAndRowSpace.y
  347. default:
  348. KMPrint("未找到")
  349. break
  350. }
  351. }
  352. NSGraphicsContext.saveGraphicsState()
  353. //平移
  354. context.translateBy(x: origin.x, y: origin.y)
  355. //缩放
  356. context.scaleBy(x: CGFloat(scale), y: CGFloat(scale))
  357. page.page.draw(with: PDFDisplayBox.cropBox, to: context)
  358. // page.transform(context, for: PDFDisplayBox.cropBox)
  359. if border {
  360. var dirtyRect = rect
  361. if rotate == 90 ||
  362. rotate == 270 {
  363. dirtyRect = NSMakeRect(dirtyRect.origin.x, dirtyRect.origin.y, dirtyRect.size.height, dirtyRect.size.width)
  364. }
  365. context.addRect(dirtyRect)
  366. context.setStrokeColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
  367. context.strokePath()
  368. }
  369. NSGraphicsContext.restoreGraphicsState()
  370. // page.setBounds(NSRect(x: 0, y: 0, width: pageRect.size.width, height: pageRect.size.height), for: .cropBox)
  371. }
  372. }
  373. }
  374. }
  375. }
  376. protocol KMPrintPresenterPage {}
  377. extension KMPrintPresenter: KMPrintPresenterPage {
  378. /**
  379. 获取pages
  380. @param type 页面类型
  381. @param contentType annoation类型
  382. @param selectPages 当type 为custom时 传入选中page的下标
  383. */
  384. func fetchPageCropRect(_ paperSize: CGSize, _ index: Int, _ pageModel: KMPrintPageModel, _ page: KMPrintDrawPage) -> CGRect {
  385. var newRect = page.page.bounds(for: .cropBox)
  386. if (pageModel.operation.type == .poster) {
  387. let originSize = newRect.size
  388. var cropPoint = CGPoint(x: 1, y: 1)
  389. var scale = 1.0
  390. if (pageModel.operation.poster.type == .tile) {
  391. cropPoint = pageModel.operation.poster.tilePoint
  392. // scale = pageModel.operation.poster.scale
  393. } else if (pageModel.operation.poster.type == .breakUp) {
  394. cropPoint = pageModel.operation.poster.pageOfPaper.point
  395. }
  396. let width = originSize.width / cropPoint.x
  397. let height = originSize.height / cropPoint.y
  398. let column: Int = Int(cropPoint.x) //行
  399. let row: Int = Int(cropPoint.y) //列
  400. for i in 0...column - 1 {
  401. for j in 0...row - 1 {
  402. if i + j + i * (row - 1) == index {
  403. newRect.origin.x = CGFloat(i) * width * scale
  404. newRect.origin.y = ((originSize.height - CGFloat(j) * height - height)) * scale
  405. newRect.size.width = width * scale
  406. newRect.size.height = height * scale
  407. return newRect
  408. }
  409. }
  410. }
  411. }
  412. return newRect
  413. }
  414. func fetchPageShowRect(_ paperSize: CGSize, _ index: Int, _ pageModel: KMPrintPageModel, _ page: KMPrintDrawPage) -> CGRect {
  415. var newRect = NSZeroRect
  416. var pageRect = CGRect(x: 0, y: 0, width: paperSize.width, height: paperSize.height)
  417. if (pageModel.operation.type == .poster) {
  418. let pageSize = page.page.bounds(for: .cropBox)
  419. var cropPoint = CGPoint(x: 1, y: 1)
  420. var scale = 1.0
  421. if (pageModel.operation.poster.type == .tile) {
  422. cropPoint = pageModel.operation.poster.tilePoint
  423. scale = pageModel.operation.poster.scale
  424. } else if (pageModel.operation.poster.type == .breakUp) {
  425. cropPoint = pageModel.operation.poster.pageOfPaper.point
  426. }
  427. if (cropPoint.x == 1 && cropPoint.y == 1) {
  428. } else {
  429. let originPaperSize = CGSize(width: paperSize.width * cropPoint.x, height: paperSize.height * cropPoint.y)
  430. let pageWidth = pageSize.width * scale
  431. let pageHeight = pageSize.height * scale
  432. let pageOrigin = CGPoint(x: (originPaperSize.width - pageWidth) / 2, y: (originPaperSize.height - pageHeight) / 2)
  433. let width = originPaperSize.width / cropPoint.x
  434. let height = originPaperSize.height / cropPoint.y
  435. let column: Int = Int(cropPoint.x) //行
  436. let row: Int = Int(cropPoint.y) //列
  437. for i in 0...column - 1 {
  438. for j in 0...row - 1 {
  439. if i + j + i * (row - 1) == index {
  440. newRect.origin.x = CGFloat(i) * width
  441. newRect.origin.y = ((originPaperSize.height - CGFloat(j) * height - height))
  442. newRect.size.width = width
  443. newRect.size.height = height
  444. if (pageOrigin.x > newRect.origin.x) {
  445. pageRect.origin.x = pageOrigin.x
  446. pageRect.size.width = newRect.size.width - pageOrigin.x
  447. } else if (originPaperSize.width - pageOrigin.x > newRect.origin.x) {
  448. pageRect.origin.x = 0
  449. pageRect.size.width = newRect.size.width - pageOrigin.x
  450. } else {
  451. pageRect.origin.x = 0
  452. pageRect.size.width = newRect.size.width
  453. }
  454. if (originPaperSize.height - pageOrigin.y < newRect.origin.y + newRect.size.height) {
  455. pageRect.origin.y = 0
  456. pageRect.size.height = newRect.size.height - pageOrigin.y
  457. } else if (pageOrigin.y > newRect.origin.y) {
  458. pageRect.origin.y = pageOrigin.y
  459. pageRect.size.height = newRect.size.height - pageOrigin.y
  460. } else {
  461. pageRect.origin.y = newRect.origin.y - pageOrigin.y
  462. pageRect.size.height = newRect.size.height
  463. }
  464. return pageRect
  465. }
  466. }
  467. }
  468. }
  469. }
  470. return pageRect
  471. }
  472. func fetchPageColumnAndRow(_ pageModel: KMPrintPageModel) -> CGPoint {
  473. var point = NSZeroPoint
  474. let pageOrder: KMPrintPageOperation.Multipage.Order = pageModel.operation.multipage.orderType //页面顺序
  475. switch pageModel.operation.type {
  476. case .multipage:
  477. point.x = pageModel.operation.multipage.pageOfPaper.point.x
  478. point.y = pageModel.operation.multipage.pageOfPaper.point.y
  479. default:
  480. point.x = 1
  481. point.y = 1
  482. }
  483. //如果是横向参数需切换
  484. if pageOrder == .horizontal ||
  485. pageOrder == .horizontalReverseSequence {
  486. let temp = point.x
  487. point.x = point.y
  488. point.y = temp
  489. }
  490. return point
  491. }
  492. func fetchAutoRotate(_ pageModel: KMPrintPageModel) -> Bool {
  493. var autoRotate = false
  494. switch pageModel.operation.type {
  495. case .multipage:
  496. autoRotate = pageModel.operation.multipage.isAutoRotate
  497. case .pamphlet:
  498. autoRotate = pageModel.operation.pamphlet.isAutoRotate
  499. default:
  500. autoRotate = false
  501. }
  502. return autoRotate
  503. }
  504. func fetchAutoSize(_ pageModel: KMPrintPageModel) -> Bool {
  505. var autoSize = false
  506. switch pageModel.operation.type {
  507. case .size:
  508. autoSize = true
  509. default:
  510. autoSize = false
  511. }
  512. return autoSize
  513. }
  514. func fetchShowModel(_ pageModel: KMPrintPageModel) -> KMPrintPageOperation.Size {
  515. var model = KMPrintPageOperation.Size()
  516. switch pageModel.operation.type {
  517. case .size:
  518. model = pageModel.operation.size
  519. default:
  520. model = KMPrintPageOperation.Size()
  521. }
  522. return model
  523. }
  524. func fetchPageItemSize(_ pageModel: KMPrintPageModel, _ paperSize: CGSize) -> CGSize {
  525. var size = NSZeroSize
  526. let columnAndRow = self.fetchPageColumnAndRow(pageModel) //行 列数量
  527. let columnAndRowSpace = CGPoint(x: 2, y: 2) //行 列之间的空间
  528. //page大小
  529. size = CGSize(width: (paperSize.width - CGFloat((columnAndRow.x - 1)) * CGFloat(columnAndRowSpace.x)) / columnAndRow.x,
  530. height: (paperSize.height - CGFloat((columnAndRow.y - 1)) * CGFloat(columnAndRowSpace.y)) / columnAndRow.y)
  531. return size
  532. }
  533. func fetchPageScale(_ page: KMPrintDrawPage, _ pageItemSize: CGSize, _ autoRotate: Bool, _ autoSize: Bool) -> CGFloat {
  534. var scale = 1.0
  535. let originSize = page.page.bounds(for: .cropBox)
  536. var rotate = page.page.rotation
  537. //取出page横竖时能显示的最大Rect
  538. if autoRotate {
  539. //page旋转度数为0度或者180度时,在指定的大小内,能显示的比例
  540. let scale1 = min(pageItemSize.width / originSize.width, pageItemSize.height / originSize.height)
  541. //page旋转度数为90度或者270度时,在指定的大小内,能显示的比例
  542. let scale2 = min(pageItemSize.width / originSize.height, pageItemSize.height / originSize.width)
  543. scale = max(scale1, scale2)
  544. if scale1 > scale2 {
  545. //高为竖直排列时,显示最大,则需将page时90度或者270度需要进行旋转
  546. if rotate == 90 || rotate == 270 {
  547. rotate = rotate - 90
  548. }
  549. } else {
  550. //宽为竖直排列时,显示最大,则需将page时0度或者180度需要进行旋转
  551. if rotate == 0 || rotate == 180 {
  552. rotate = rotate - 90
  553. }
  554. }
  555. } else {
  556. scale = min(pageItemSize.width / originSize.width, pageItemSize.height / originSize.height)
  557. }
  558. if (autoSize) {
  559. } else {
  560. scale = min(scale, 1)
  561. }
  562. return scale
  563. }
  564. func fetchPageRotate(_ page: KMPrintDrawPage, _ pageItemSize: CGSize, _ autoRotate: Bool) -> CGFloat {
  565. var scale = 1.0
  566. let originSize = page.page.bounds(for: .cropBox)
  567. var rotate = page.page.rotation
  568. //取出page横竖时能显示的最大Rect
  569. if autoRotate {
  570. //page旋转度数为0度或者180度时,在指定的大小内,能显示的比例
  571. let scale1 = min(pageItemSize.width / originSize.width, pageItemSize.height / originSize.height)
  572. //page旋转度数为90度或者270度时,在指定的大小内,能显示的比例
  573. let scale2 = min(pageItemSize.width / originSize.height, pageItemSize.height / originSize.width)
  574. scale = max(scale1, scale2)
  575. if scale1 > scale2 {
  576. //高为竖直排列时,显示最大,则需将page时90度或者270度需要进行旋转
  577. if rotate == 90 || rotate == 270 {
  578. rotate = rotate - 90
  579. }
  580. } else {
  581. //宽为竖直排列时,显示最大,则需将page时0度或者180度需要进行旋转
  582. if rotate == 0 || rotate == 180 {
  583. rotate = rotate - 90
  584. }
  585. }
  586. } else {
  587. scale = min(pageItemSize.width / originSize.width, pageItemSize.height / originSize.height)
  588. }
  589. return scale
  590. }
  591. func fetchPageLite(pageModel: KMPrintPageModel) {
  592. }
  593. }
  594. protocol KMPrintPresenterPaper {}
  595. extension KMPrintPresenter: KMPrintPresenterPaper {
  596. /**
  597. 获取每张纸的page
  598. @param type 页面类型
  599. @param contentType annoation类型
  600. @param selectPages 当type 为custom时 传入选中page的下标
  601. */
  602. func fetchPageOfPaper(_ pageModel: KMPrintPageModel) -> Int {
  603. var count = 1
  604. switch pageModel.operation.type {
  605. case .multipage:
  606. count = Int(pageModel.operation.multipage.pageOfPaper.point.x * pageModel.operation.multipage.pageOfPaper.point.y)
  607. case .poster:
  608. count = Int(pageModel.operation.multipage.pageOfPaper.point.x * pageModel.operation.multipage.pageOfPaper.point.y)
  609. default:
  610. count = 1
  611. }
  612. return count
  613. }
  614. /**
  615. 获取总纸张数
  616. @param pages page总数
  617. @param contentType annoation类型
  618. @param selectPages 当type 为custom时 传入选中page的下标
  619. */
  620. func fetchTotalPaperCount (_ paperSize: CGSize, _ pages: [KMPrintDrawPage], _ pageModel: KMPrintPageModel) -> Int {
  621. var count = 1
  622. let pageOfPaper = self.fetchPageOfPaper(pageModel)
  623. switch pageModel.operation.type {
  624. case .multipage:
  625. count = Int(ceilf(Float(pages.count / pageOfPaper)))
  626. case .poster:
  627. if (pageModel.operation.poster.type == .tile) {
  628. //1 2 4 9 16
  629. let scale = pageModel.operation.poster.scale
  630. let pageSize = pages.first?.page.bounds(for: .cropBox).size ?? paperSize
  631. let point = self.fetchPosterPageCount(paperSize: paperSize, pageSize: pageSize, scale: scale)
  632. pageModel.operation.poster.tilePoint = point
  633. count = Int((point.x * point.y)) * pages.count
  634. } else if (pageModel.operation.poster.type == .breakUp) {
  635. count = Int((pageModel.operation.poster.pageOfPaper.point.x * pageModel.operation.poster.pageOfPaper.point.y)) * pages.count
  636. } else {
  637. count = Int(ceilf(Float(pages.count / pageOfPaper)))
  638. }
  639. default:
  640. count = Int(ceilf(Float(pages.count / pageOfPaper)))
  641. }
  642. return count
  643. }
  644. func fetchPosterPageCount(paperSize: CGSize, pageSize: CGSize, scale: CGFloat) -> CGPoint {
  645. var xCount: Int = 1
  646. var yCount: Int = 1
  647. var contain: Bool = true
  648. while (contain) {
  649. if (pageSize.width * scale < CGFloat(xCount) * paperSize.width &&
  650. pageSize.height * scale < CGFloat(yCount) * paperSize.height) {
  651. contain = false
  652. break
  653. }
  654. //增加行数 和 列数
  655. if xCount == yCount {
  656. xCount += 1
  657. } else {
  658. yCount += 1
  659. }
  660. }
  661. return CGPoint(x: xCount, y: yCount)
  662. }
  663. /**
  664. 获取pages
  665. @param type 页面类型
  666. @param contentType annoation类型
  667. @param selectPages 当type 为custom时 传入选中page的下标
  668. */
  669. func fetchPaperSize(_ paperModel: KMPrintPaperModel) -> CGSize {
  670. var paperSize = paperModel.info.size
  671. let direction = paperModel.direction
  672. if direction == .vertical {
  673. paperSize = CGSize(width: paperModel.info.size.width, height: paperModel.info.size.height)
  674. } else if direction == .horizontal {
  675. paperSize = CGSize(width: paperModel.info.size.height, height: paperModel.info.size.width)
  676. }
  677. return paperSize
  678. }
  679. func fetchPaperItemSize(_ paperModel: KMPrintPaperModel) -> CGSize {
  680. var paperSize = self.fetchPaperSize(paperModel)
  681. let paperInset = paperModel.info.inset
  682. paperSize = CGSize(width: paperSize.width - paperInset.left - paperInset.right,
  683. height: paperSize.height - paperInset.bottom - paperInset.top)
  684. return paperSize
  685. }
  686. }
  687. protocol KMPrintPresenterDraw {}
  688. extension KMPrintPresenter: KMPrintPresenterDraw {
  689. // -(void)drawCutMarkContext:(CGContextRef)context contextSize:(CGSize)size
  690. // {
  691. // CGContextSetStrokeColorWithColor(context, [NSColor blackColor].CGColor);
  692. // CGContextSetLineWidth(context, 1.0);
  693. // CGContextSetLineCap(context, kCGLineCapSquare);
  694. //
  695. // if(self.columnIndex == 1 && self.lineIndex == 1) {
  696. // [self drawLeftBottomCutMarks:context size:size];
  697. // [self drawRightTopCutMarks:context size:size];
  698. // [self drawRightBottomCutMarks:context size:size];
  699. // } else if (self.lineIndex == 1 && self.columnIndex == self.vertArray.count) {
  700. // [self drawLeftTopCutMarks:context size:size];
  701. // [self drawRightTopCutMarks:context size:size];
  702. // [self drawRightBottomCutMarks:context size:size];
  703. // } else if (self.columnIndex == 1 && self.lineIndex == self.hourArray.count) {
  704. // [self drawLeftTopCutMarks:context size:size];
  705. // [self drawLeftBottomCutMarks:context size:size];
  706. // [self drawRightBottomCutMarks:context size:size];
  707. // } else if (self.columnIndex == self.vertArray.count && self.hourArray.count == self.lineIndex) {
  708. // [self drawLeftTopCutMarks:context size:size];
  709. // [self drawLeftBottomCutMarks:context size:size];
  710. // [self drawRightTopCutMarks:context size:size];
  711. // } else {
  712. // [self drawLeftTopCutMarks:context size:size];
  713. // [self drawLeftBottomCutMarks:context size:size];
  714. // [self drawRightTopCutMarks:context size:size];
  715. // [self drawRightBottomCutMarks:context size:size];
  716. // }
  717. // //绘制完成
  718. // CGContextStrokePath(context);
  719. // }
  720. //
  721. // //左上角切割标记
  722. // -(void)drawLeftTopCutMarks:(CGContextRef)context size:(CGSize)size
  723. // {
  724. // CGFloat KBlankA4H =size.height;
  725. // CGPoint point_LeftTop = CGPointZero;
  726. //
  727. // if (self.PDFPrint.splitType == kKMPDFPosterSplitType_PageNumber) {
  728. // point_LeftTop.x = self.PDFPrint.fullPageEdgeInsets.left;
  729. // } else {
  730. // point_LeftTop.x = self.PDFPrint.edgeInsets.left;
  731. // }
  732. //
  733. // point_LeftTop.y = KBlankA4H - self.PDFPrint.edgeInsets.top;
  734. //
  735. // CGContextMoveToPoint(context, 10,point_LeftTop.y);
  736. // CGContextAddLineToPoint(context,point_LeftTop.x, point_LeftTop.y);
  737. //
  738. // CGContextMoveToPoint(context, point_LeftTop.x - 10,KBlankA4H -10);
  739. // CGContextAddLineToPoint(context,point_LeftTop.x - 10,point_LeftTop.y);
  740. // }
  741. //
  742. // //右上角切割标记
  743. // -(void)drawRightTopCutMarks:(CGContextRef)context size:(CGSize)size
  744. // {
  745. // CGFloat KBlankA4W =size.width;
  746. // CGFloat KBlankA4H =size.height;
  747. //
  748. // CGPoint point_RightTop = CGPointZero;//右上角
  749. //
  750. // if (self.PDFPrint.splitType == kKMPDFPosterSplitType_PageNumber) {
  751. // point_RightTop.x = KBlankA4W - self.PDFPrint.fullPageEdgeInsets.right;
  752. // point_RightTop.y = KBlankA4H - self.PDFPrint.fullPageEdgeInsets.top;
  753. // } else {
  754. // point_RightTop.x = KBlankA4W - self.PDFPrint.edgeInsets.right;
  755. // point_RightTop.y = KBlankA4H - self.PDFPrint.edgeInsets.top;
  756. // }
  757. //
  758. // CGContextMoveToPoint(context,point_RightTop.x,point_RightTop.y);
  759. // CGContextAddLineToPoint(context,KBlankA4W - 10,point_RightTop.y);
  760. //
  761. // CGContextMoveToPoint(context,point_RightTop.x + 10,KBlankA4H - 10);
  762. // CGContextAddLineToPoint(context,point_RightTop.x + 10,point_RightTop.y);
  763. // }
  764. //
  765. // //左下角切割标记
  766. // -(void)drawLeftBottomCutMarks:(CGContextRef)context size:(CGSize)size
  767. // {
  768. // CGPoint point_LeftBottom = CGPointZero;//左下角
  769. // if (self.PDFPrint.splitType == kKMPDFPosterSplitType_PageNumber) {
  770. // point_LeftBottom.x = self.PDFPrint.fullPageEdgeInsets.left;
  771. // point_LeftBottom.y = self.PDFPrint.fullPageEdgeInsets.bottom;
  772. // } else {
  773. // point_LeftBottom.x = self.PDFPrint.edgeInsets.left;
  774. // point_LeftBottom.y = self.PDFPrint.edgeInsets.bottom;
  775. // }
  776. //
  777. // //左下角
  778. // CGContextMoveToPoint(context, 10,point_LeftBottom.y);
  779. // CGContextAddLineToPoint(context,point_LeftBottom.x, point_LeftBottom.y);
  780. //
  781. // CGContextMoveToPoint(context, point_LeftBottom.x- 10,10);
  782. // CGContextAddLineToPoint(context,point_LeftBottom.x - 10,point_LeftBottom.y);
  783. // }
  784. //
  785. // //右下角切割标记
  786. // -(void)drawRightBottomCutMarks:(CGContextRef)context size:(CGSize)size
  787. // {
  788. // CGFloat KBlankA4W =size.width;
  789. //
  790. // CGPoint point_RightBottom = CGPointZero;//右下角
  791. // if (self.PDFPrint.splitType == kKMPDFPosterSplitType_PageNumber) {
  792. // point_RightBottom.x = KBlankA4W - self.PDFPrint.fullPageEdgeInsets.right;
  793. // point_RightBottom.y = self.PDFPrint.fullPageEdgeInsets.bottom;
  794. // } else {
  795. // point_RightBottom.x = KBlankA4W - self.PDFPrint.edgeInsets.right;
  796. // point_RightBottom.y = self.PDFPrint.edgeInsets.bottom;
  797. // }
  798. //
  799. // CGContextMoveToPoint(context,KBlankA4W - 10,point_RightBottom.y);
  800. // CGContextAddLineToPoint(context,point_RightBottom.x,point_RightBottom.y);
  801. //
  802. // CGContextMoveToPoint(context,point_RightBottom.x+ 10,10);
  803. // CGContextAddLineToPoint(context,point_RightBottom.x+ 10,point_RightBottom.y);
  804. // }
  805. func drawString(_ pageModel: KMPrintPageModel, _ contextSize: CGSize) {
  806. var string = pageModel.operation.poster.tags.first ?? ""
  807. // if string.isEmpty {
  808. // string =
  809. // }
  810. }
  811. //
  812. // - (void)drawLabelTextContextSize:(CGSize)contextSize
  813. // {
  814. // CGFloat KBlankA4W =contextSize.width;
  815. // CGFloat KBlankA4H =contextSize.height;
  816. //
  817. // NSString *contextString = nil;
  818. // if (self.PDFPrint.labelString && self.PDFPrint.labelString.length > 0) {
  819. // contextString = self.PDFPrint.labelString;
  820. // } else {
  821. // NSDate *date = [NSDate date];
  822. // NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
  823. // [formatter setDateFormat:@"YYYY-MM-dd hh:mm:ss"];
  824. // contextString = [NSString stringWithFormat:@"(%ld,%ld) %@ %@",self.columnIndex,self.lineIndex,[self.filePath lastPathComponent],[formatter stringFromDate:date]];
  825. // }
  826. //
  827. // CGFloat fontSize = 12.0 * (MAX(KBlankA4W, KBlankA4H)/842);
  828. // NSFont *font = [NSFont systemFontOfSize:fontSize];
  829. // NSColor *color = [NSColor blackColor];
  830. //
  831. // NSSize size = NSZeroSize;
  832. // NSMutableParagraphStyle *style = [[[NSMutableParagraphStyle alloc] init] autorelease];
  833. // [style setAlignment:NSCenterTextAlignment];
  834. // [style setLineBreakMode:NSLineBreakByCharWrapping];
  835. // NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
  836. // [dictionary setObject:style forKey:NSParagraphStyleAttributeName];
  837. // [dictionary setObject:color forKey:NSForegroundColorAttributeName];
  838. // [dictionary setObject:font forKey:NSFontAttributeName];
  839. // size = [contextString boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
  840. // options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  841. // attributes:dictionary].size;
  842. //
  843. // if (self.PDFPrint.splitType == kKMPDFPosterSplitType_PageNumber) {
  844. // [contextString drawInRect:CGRectMake(self.PDFPrint.fullPageEdgeInsets.left +10,
  845. // KBlankA4H - self.PDFPrint.fullPageEdgeInsets.top + size.height,
  846. // size.width, size.height)
  847. // withAttributes:dictionary];
  848. // } else {
  849. // [contextString drawInRect:CGRectMake(self.PDFPrint.edgeInsets.left +10,
  850. // KBlankA4H - self.PDFPrint.edgeInsets.top + size.height,
  851. // size.width, size.height)
  852. // withAttributes:dictionary];
  853. // }
  854. //
  855. // }
  856. }
  857. protocol KMPrintPresenterPrivate {}
  858. extension KMPrintPresenter: KMPrintPresenterPrivate {
  859. func isAnnoationStamp(type: String) -> Bool {
  860. let annotationStamp: [String] = ["Square"]
  861. return annotationStamp.contains(type)
  862. }
  863. func isAnnoationMarkup(type: String) -> Bool {
  864. let annotationStamp: [String] = ["Widget", "Freehand"]
  865. return annotationStamp.contains(type)
  866. }
  867. func isAnnoationForm(type: String) -> Bool {
  868. let annotationStamp: [String] = ["FreeText"]
  869. return annotationStamp.contains(type)
  870. }
  871. }
  872. protocol KMPrintPresenterProtocol: NSObject {
  873. }
  874. ///**
  875. // @abstract 获取context
  876. // @param size纸张大小
  877. // */
  878. //func createContext(_ saveFilePath: String, size: CGSize) -> CGContext {
  879. // let s = CGSize(width: nearbyint(size.width), height: nearbyint(size.height))
  880. // let rep = NSBitmapImageRep.init(bitmapDataPlanes: nil,
  881. // pixelsWide: Int(s.width),
  882. // pixelsHigh: Int(s.height),
  883. // bitsPerSample: 8,
  884. // samplesPerPixel: 4,
  885. // hasAlpha: true,
  886. // isPlanar: false,
  887. // colorSpaceName: NSColorSpaceName.calibratedRGB,
  888. // bytesPerRow: 0,
  889. // bitsPerPixel: 0)!
  890. // let context: CGContext = NSGraphicsContext.init(bitmapImageRep: rep)!.cgContext
  891. // return context
  892. //}