KMPrintPresenter.swift 45 KB

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