KMCropPreviewController.swift 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  1. //
  2. // KMCropPreviewController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by tangchao on 2022/12/29.
  6. //
  7. import Cocoa
  8. import PDFKit
  9. extension CPDFPage {
  10. private static var _drawingPage = "cropDrawingPage"
  11. var cropDrawingPage: CPDFPage? {
  12. get {
  13. return (objc_getAssociatedObject(self, &CPDFPage._drawingPage) as? CPDFPage)
  14. }
  15. set {
  16. objc_setAssociatedObject(self, &CPDFPage._drawingPage, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
  17. }
  18. }
  19. var cropOffsetX: CGFloat {
  20. get {
  21. return objc_getAssociatedObject(self, "cropOffsetX") as! CGFloat
  22. }
  23. set {
  24. objc_setAssociatedObject(self, "cropOffsetX", newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_ASSIGN)
  25. }
  26. }
  27. var cropOffsetY: CGFloat {
  28. get {
  29. return objc_getAssociatedObject(self, "cropOffsetY") as! CGFloat
  30. }
  31. set {
  32. objc_setAssociatedObject(self, "cropOffsetY", newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_ASSIGN)
  33. }
  34. }
  35. var isChangePageSize: Bool {
  36. get {
  37. return objc_getAssociatedObject(self, "isChangePageSize") as! Bool
  38. }
  39. set {
  40. objc_setAssociatedObject(self, "isChangePageSize", newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_ASSIGN)
  41. }
  42. }
  43. var cropRect: NSRect {
  44. get {
  45. return objc_getAssociatedObject(self, "cropRect") as! NSRect
  46. }
  47. set {
  48. objc_setAssociatedObject(self, "cropRect", newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_ASSIGN)
  49. }
  50. }
  51. }
  52. class KMCropInfo: NSObject {
  53. var drawPage: CPDFPage!
  54. var cropOffsetX: CGFloat = 0
  55. var cropOffsetY: CGFloat = 0
  56. var isChangePageSize: Bool = false
  57. var cropRect: NSRect!
  58. }
  59. class KMCropPDFView: CPDFView {
  60. var drawInfo: Array<KMCropInfo> = []
  61. override func draw(_ page: CPDFPage!, to context: CGContext!) {
  62. super.draw(page, to: context)
  63. if (self.drawInfo.count > 0) {
  64. drawCropPage(page, to: context)
  65. }
  66. drawCropPage(page: page, toContext: context)
  67. }
  68. private func drawCropPage(page: CPDFPage, toContext context: CGContext) {
  69. if (page.cropDrawingPage != nil) {
  70. let originalRect = page.bounds(for: .mediaBox)
  71. let drawPage = page.cropDrawingPage
  72. let cropRect = drawPage?.bounds(for: .mediaBox)
  73. let orgPageWidth = cropRect?.size.width
  74. let orgPageHeight = cropRect?.size.height
  75. let spaceX = page.cropOffsetX
  76. let spaceY = page.cropOffsetY
  77. let scanl = min(originalRect.size.width/(orgPageWidth ?? 0), originalRect.size.height/(orgPageHeight ?? 1))
  78. NSGraphicsContext.saveGraphicsState()
  79. context.translateBy(x: spaceX, y: spaceY)
  80. context.scaleBy(x: scanl, y: scanl)
  81. if #available(macOS 10.12, *) {
  82. drawPage?.draw(with: .cropBox, to: context)
  83. drawPage?.transform(context, for: .cropBox)
  84. } else {
  85. NSGraphicsContext.saveGraphicsState()
  86. NSGraphicsContext.current = NSGraphicsContext(cgContext: context, flipped: true)
  87. drawPage?.draw(with: .cropBox, to: context)
  88. NSGraphicsContext.restoreGraphicsState()
  89. drawPage?.transform(context, for: .cropBox)
  90. }
  91. if !page.isChangePageSize {
  92. let tCropRect = page.cropRect
  93. let w1 = (orgPageWidth ?? 0) - tCropRect.size.width - tCropRect.origin.x
  94. context.setFillColor(red: 0, green: 0, blue: 0, alpha: 0.3)
  95. let rect1 = CGRect(x: 0, y: 0, width: orgPageWidth ?? 0, height: tCropRect.origin.y)
  96. let rect2 = CGRect(x: 0, y: tCropRect.origin.y + tCropRect.size.height, width: orgPageWidth ?? 0, height: (orgPageHeight ?? 0) - tCropRect.origin.y - tCropRect.size.height)
  97. let rect3 = CGRect(x: 0, y: tCropRect.origin.y, width: tCropRect.origin.x, height: tCropRect.size.height)
  98. let rect4 = CGRect(x: tCropRect.origin.x + tCropRect.size.width, y: tCropRect.origin.y, width: max(w1, 0), height: tCropRect.size.height)
  99. context.fill(rect1)
  100. context.fill(rect2)
  101. context.fill(rect3)
  102. context.fill(rect4)
  103. }
  104. NSGraphicsContext.restoreGraphicsState()
  105. }
  106. }
  107. private func drawCropPage(_ cropPage: CPDFPage, to context: CGContext!) {
  108. // let myPage: KMCropPDFPage = cropPage as! KMCropPDFPage
  109. let info: KMCropInfo = self.drawInfo[Int(self.document.index(for: cropPage))]
  110. if (info.drawPage != nil) {
  111. let originalRect = cropPage.bounds(for: .mediaBox)
  112. let drawPage = info.drawPage
  113. let cropRect = drawPage!.bounds(for: .mediaBox)
  114. /// 原始page的宽度(不管有没有旋转,都是旋转度数等于0)
  115. let orgPageWidth: CGFloat = NSWidth(cropRect)
  116. /// 原始page的高度
  117. let orgPageHeight: CGFloat = NSHeight(cropRect)
  118. let spaceX = info.cropOffsetX
  119. let spaceY = info.cropOffsetY
  120. let scale: CGFloat = min(NSWidth(originalRect)/orgPageWidth, NSHeight(originalRect)/orgPageHeight)
  121. NSGraphicsContext.saveGraphicsState()
  122. context.translateBy(x: spaceX,y: spaceY)
  123. context.scaleBy(x: scale, y: scale)
  124. if #available(macOS 10.12, *) {
  125. drawPage?.draw(with: .cropBox, to: context)
  126. drawPage?.transform(context, for: .cropBox)
  127. } else {
  128. NSGraphicsContext.saveGraphicsState()
  129. NSGraphicsContext.current = NSGraphicsContext(cgContext: context, flipped: false)
  130. drawPage?.draw(with: .cropBox, to: context)
  131. drawPage?.transform(context, for: .cropBox)
  132. }
  133. if (info.isChangePageSize) {
  134. let tCropRect: NSRect = cropPage.cropRect
  135. let w1: CGFloat = orgPageWidth-(tCropRect.size.width)-(tCropRect.origin.x)
  136. context.setFillColor(red: 0, green: 0, blue: 0, alpha: 0.3)
  137. let rect1: NSRect = NSMakeRect(0, 0, orgPageWidth, (tCropRect.origin.y))
  138. let rect2: NSRect = NSMakeRect(0, (tCropRect.origin.y)+(tCropRect.size.height), orgPageWidth, orgPageHeight - tCropRect.origin.y-tCropRect.size.height)
  139. let rect3: NSRect = NSMakeRect(0, tCropRect.origin.y,tCropRect.origin.x,tCropRect.size.height);
  140. var rect4Y = w1
  141. if (w1 > 0) {
  142. rect4Y = 0
  143. }
  144. let rect4: NSRect = NSMakeRect(tCropRect.origin.x+tCropRect.size.width, tCropRect.origin.y,rect4Y,tCropRect.size.height)
  145. context.fill(rect1)
  146. context.fill(rect2)
  147. context.fill(rect3)
  148. context.fill(rect4)
  149. }
  150. NSGraphicsContext.restoreGraphicsState()
  151. }
  152. }
  153. }
  154. class KMCropPDFPage: CPDFPage {
  155. // var drawingPage: CPDFPage!
  156. // var cropOffsetX: CGFloat = 0
  157. // var cropOffsetY: CGFloat = 0
  158. // var isChangePageSize: Bool = false
  159. // var cropRect: NSRect!
  160. override func draw(with box: CPDFDisplayBox, to context: CGContext!) {
  161. super.draw(with: box, to: context)
  162. let pageSize: NSSize = self.bounds(for: .mediaBox).size
  163. drawPage(with: context, page: self.cropDrawingPage!, pageSize: pageSize)
  164. }
  165. private func drawPage(with context: CGContext, page: CPDFPage, pageSize: NSSize) {
  166. let myPage: KMCropPDFPage = page as! KMCropPDFPage
  167. var originalSize: NSSize = page.bounds(for: .mediaBox).size
  168. //如果page的旋转角度为90,或者270,宽高交换
  169. if (page.rotation % 180 != 0) {
  170. originalSize = NSMakeSize(originalSize.height, originalSize.width)
  171. }
  172. context.saveGState()
  173. context.translateBy(x: myPage.cropOffsetX, y: myPage.cropOffsetY)
  174. if #available(macOS 10.12, *) {
  175. page.draw(with: .cropBox, to: context)
  176. page.transform(context, for: .cropBox)
  177. } else {
  178. NSGraphicsContext.saveGraphicsState()
  179. NSGraphicsContext.current = NSGraphicsContext(cgContext: context, flipped: true)
  180. page.draw(with: .cropBox, to: context)
  181. NSGraphicsContext.restoreGraphicsState()
  182. page.transform(context, for: .cropBox)
  183. }
  184. context.restoreGState()
  185. }
  186. }
  187. class KMCropPreviewController: KMWatermarkAdjectivePreViewBaseController {
  188. // var testPreView: PDFView!
  189. var tipView = KMCropTipView()
  190. var windowController: KMCropSettingWindowController!
  191. override func viewDidLoad() {
  192. super.viewDidLoad()
  193. let itemTitles = [["裁剪"]]
  194. var itemModels: Array<Array<KMWatermarkAdjectiveTopBarItemModel>> = []
  195. for items in itemTitles {
  196. var array: Array<KMWatermarkAdjectiveTopBarItemModel> = []
  197. for title in items {
  198. let model = KMWatermarkAdjectiveTopBarItemModel()
  199. model.iconName = ""
  200. model.itemTitle = title
  201. array.append(model)
  202. }
  203. itemModels.append(array)
  204. }
  205. self.topBarView.initItemData(itemArrays: itemModels)
  206. let preView: CPDFListView = CPDFListView()
  207. self.preView = preView
  208. self.preView.frame = self.preViewBox.contentView!.bounds
  209. self.preView.autoresizingMask = NSView.AutoresizingMask(rawValue: 18)
  210. self.preViewBox.contentView?.addSubview(self.preView)
  211. self.preView.autoScales = true
  212. self.preView.displaysAsBook = true
  213. self.preView.delegate = self
  214. let myPreView: CPDFListView = self.preView as! CPDFListView
  215. myPreView.pdfListViewDelegate = self
  216. // NotificationCenter.default.addObserver(self, selector: #selector(preViewSelectionDidChange), name: NSNotification.Name.CPDFViewSelectionChanged, object: nil)
  217. // self.testPreView = PDFView()
  218. // self.testPreView.frame = self.preViewBox.contentView!.bounds
  219. // self.testPreView.autoresizingMask = NSView.AutoresizingMask(rawValue: 18)
  220. // self.preViewBox.contentView?.addSubview(self.testPreView)
  221. self.topBarView.isCanApply(can: false)
  222. self.tipView.frame = self.tipBox.contentView!.frame
  223. self.tipView.autoresizingMask = NSView.AutoresizingMask(rawValue: 18)
  224. self.tipBox.addSubview(self.tipView)
  225. self.tipBox.isHidden = true
  226. self.tipView.enterAction = {
  227. () in
  228. let myPreView: CPDFListView = self.preView as! CPDFListView
  229. var rect = NSIntegralRect(myPreView.currentSelectionRect())
  230. if (NSIsEmptyRect(rect)) {
  231. return
  232. }
  233. let window = KMCropSettingWindowController(windowNibName: "KMCropSettingWindowController")
  234. self.view.window?.beginSheet(window.window!)
  235. self.windowController = window
  236. window.itemClick = { [self]
  237. (index: Int) in
  238. if (index == 1) { /// 取消
  239. self.view.window?.endSheet((self.windowController?.window)!)
  240. self.windowController = nil
  241. return
  242. }
  243. let pageRangeType = self.windowController.pageRangeIndex
  244. let pageCount: Int = Int(self.preView.document.pageCount)
  245. var pages: Array<Int> = []
  246. if (pageRangeType == 0) { /// 当前页面
  247. pages.append(self.preView.currentPageIndex)
  248. } else if (pageRangeType == 1) { /// 全部页面
  249. for i in 0 ..< pageCount {
  250. pages.append(i)
  251. }
  252. } else if (pageRangeType == 2) { /// 奇数页面
  253. var string: String = ""
  254. for i in 0 ..< pageCount {
  255. if (i % 2 == 1) {
  256. continue
  257. }
  258. pages.append(i)
  259. }
  260. } else if (pageRangeType == 3) { /// 偶数页面
  261. var string: String = ""
  262. for i in 0 ..< pageCount {
  263. if (i % 2 == 0) {
  264. continue
  265. }
  266. pages.append(i)
  267. }
  268. } else { /// 自定义
  269. for i in self.windowController.pageRangePages {
  270. pages.append(i)
  271. }
  272. }
  273. if (pages.count < 0) {
  274. let alert = NSAlert()
  275. alert.messageText = "请选择页面"
  276. alert.runModal()
  277. return
  278. }
  279. var pageSize: NSSize = NSZeroSize
  280. if (self.windowController.pageSize == "None") {
  281. } else {
  282. pageSize = KMCropTools.getPageSizeValue(self.windowController.pageSize)
  283. }
  284. for i in pages {
  285. let myPreView: CPDFListView = self.preView as! CPDFListView
  286. var page: CPDFPage = self.preView.document.page(at: UInt(i))
  287. var rect = NSIntegralRect(myPreView.selectionRect)
  288. if (NSIsEmptyRect(rect)) {
  289. rect = getPageForegroundBox(page)
  290. }
  291. var newRect = NSIntersectionRect(rect, (page.bounds(for: .mediaBox)))
  292. page.setBounds(newRect, for: .cropBox)
  293. if (pageSize.width == 0 && pageSize.height == 0) {
  294. } else {
  295. let tiffData = page.PDFListViewTIFFData(for: rect)
  296. let index: UInt = (page.pageIndex())
  297. // let newPage: CPDFPage = CPDFPage(image: NSImage(data: tiffData!))
  298. self.preView.document.removePage(at: index)
  299. // newPage.setBounds(NSMakeRect(0, 0, pageSize.width, pageSize.height), for: .cropBox)
  300. // let result = self.preView.document.insertPageObject(newPage, at: index)
  301. let result = self.preView.document.insertPage(pageSize, at: index)
  302. }
  303. }
  304. /// 保存到临时路径
  305. let toPath: String = self.preView.document.documentURL.path
  306. let documentPath = NSTemporaryDirectory()
  307. let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
  308. if (FileManager.default.fileExists(atPath: tempPath)) {
  309. try?FileManager.default.removeItem(atPath: tempPath)
  310. }
  311. let result = self.preView.document.write(to: URL(fileURLWithPath: tempPath))
  312. if (result) {
  313. if (FileManager.default.fileExists(atPath: toPath)) {
  314. try?FileManager.default.removeItem(atPath: toPath)
  315. }
  316. try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
  317. } else {
  318. try?FileManager.default.removeItem(atPath: tempPath)
  319. }
  320. DispatchQueue.main.async {
  321. let myPreView: CPDFListView = self.preView as! CPDFListView
  322. myPreView.toolMode = .textToolMode
  323. /// 刷新预览视图
  324. self.preView.layoutDocumentView()
  325. self.preView.displayBox = .cropBox
  326. }
  327. /// 裁剪
  328. self.view.window?.endSheet((self.windowController?.window)!)
  329. self.windowController = nil
  330. // self.cropCurrentPage(in: NSZeroSize)
  331. let count: Int = Int(self.preView.document!.pageCount)
  332. // let PDFView = KMCropPDFView()
  333. // PDFView.frame = self.preView.bounds
  334. // self.preView.superview?.addSubview(PDFView)
  335. // PDFView.document = CPDFDocument(url: self.preView.document.documentURL)
  336. // for i in 0 ..< count {
  337. // let page: KMCropPDFPage = KMCropPDFPage()
  338. // page.setBounds(NSMakeRect(0, 0, 200, 200), for: .mediaBox)
  339. // let cropPage = self.preView.document.page(at: UInt(i))
  340. // page.cropDrawingPage = cropPage
  341. //// self.preView.document.insertPageObject(page, at: UInt(i))
  342. //// self.preView.document.removePage(at: UInt(i))
  343. // let currentPage = page.cropDrawingPage
  344. // let drawInfo = KMCropInfo()
  345. // drawInfo.drawPage = cropPage
  346. // PDFView.drawInfo.append(drawInfo)
  347. // PDFView.document.insertPageObject(page, at: UInt(i))
  348. // }
  349. /// 保存到临时路径
  350. // let toPath: String = self.preView.document.documentURL.lastPathComponent
  351. // let documentPath = NSTemporaryDirectory()
  352. // let tempPath: String = "\(documentPath)/\(toPath)"
  353. // if (FileManager.default.fileExists(atPath: tempPath)) {
  354. // try?FileManager.default.removeItem(atPath: tempPath)
  355. // }
  356. //
  357. // let result = PDFView.document.write(to: URL(fileURLWithPath: tempPath))
  358. //
  359. // DispatchQueue.main.async {
  360. // let myPreView: CPDFListView = self.preView as! CPDFListView
  361. // myPreView.toolMode = .textToolMode
  362. //
  363. // self.preView.layoutDocumentView()
  364. // }
  365. }
  366. }
  367. }
  368. // @objc func preViewSelectionDidChange(sender: NSNotification) {
  369. // if (self.preView.isEqual(to: sender.object)) {
  370. //// self.preView.currentSelection
  371. // print("1111111111")
  372. //
  373. //// NSUInteger eventMask = NSEventMaskLeftMouseUp | NSEventMaskLeftMouseDragged;
  374. //// let theEvent = [self.view.window.nextEventMatchingMask:NSEventMaskLeftMouseUp];
  375. //// let theEvent = self.view.window?.nextEvent(matching: .leftMouseUp.union(.rightMouseUp).union(.otherMouseUp))
  376. //// if (theEvent?.type == .leftMouseUp) {
  377. // let myPreview: CPDFListView = self.preView as! CPDFListView
  378. // if (NSIsEmptyRect(myPreview.selectionRect)) {
  379. // print("end")
  380. // }
  381. // }
  382. // }
  383. override func viewDidAppear() {
  384. super.viewDidAppear()
  385. // if (self.documentURL != nil) {
  386. // self.testPreView.document = PDFDocument(url: self.documentURL)
  387. // }
  388. }
  389. override func topItemClick(index: Int) {
  390. let menu = NSMenu()
  391. let titles = ["裁剪当前页面 - 白边距", "裁剪所有页面 - 自动", "自定义裁剪区域"]
  392. for title in titles {
  393. let item = NSMenuItem(title: title, action: #selector(itemAction), target: self)
  394. item.tag = titles.firstIndex(of: title)!
  395. menu.addItem(item)
  396. }
  397. menu.popUp(positioning: nil, at: NSPoint(x: self.topBarView.frame.midX-100, y: 0), in: self.topBarView)
  398. }
  399. @objc private func itemAction(sender: NSMenuItem) {
  400. if (sender.tag == 0) {
  401. /// 裁剪当前页面 - 白边距
  402. self.tipBox.isHidden = true
  403. cropCurrentPage()
  404. return
  405. }
  406. if (sender.tag == 1) {
  407. /// 裁剪所有页面 - 自动
  408. self.tipBox.isHidden = true
  409. cropAllPate()
  410. return
  411. }
  412. //// 自定义裁剪区域
  413. let myPreView: CPDFListView = self.preView as! CPDFListView
  414. myPreView.toolMode = .selectToolMode
  415. self.preView.autoScales = true
  416. self.preView.autoScales = false
  417. var pageHeight: CGFloat = NSHeight(self.preView.currentPage().bounds(for: self.preView.displayBox))
  418. if (self.preView.displaysPageBreaks) {
  419. pageHeight += 8
  420. }
  421. var scaleFactor: CGFloat = fmax(self.preView.minimumScaleFactor, NSHeight(self.preView.frame)/pageHeight)
  422. // if (scaleFactor < self.preView.scaleFactor) {
  423. self.preView.scaleFactor = scaleFactor
  424. // }
  425. self.tipBox.isHidden = false
  426. self.tipView.setString(string: "请框选裁剪区域")
  427. }
  428. private func cropCurrentPage(in pageSize: NSSize) {
  429. let myPreView: CPDFListView = self.preView as! CPDFListView
  430. var rect = NSIntegralRect(myPreView.currentSelectionRect())
  431. var page: CPDFPage?
  432. if ((myPreView.currentSelectionPage()) != nil) {
  433. page = myPreView.currentSelectionPage()
  434. } else {
  435. page = myPreView.currentPage()
  436. }
  437. if (NSIsEmptyRect(rect)) {
  438. rect = getPageForegroundBox(page!)
  439. }
  440. let tiffData = page!.PDFListViewTIFFData(for: rect)
  441. let index: UInt = (page?.pageIndex())!
  442. var newRect = NSIntersectionRect(rect, (page?.bounds(for: .mediaBox))!)
  443. page?.setBounds(newRect, for: .cropBox)
  444. self.preView.document.removePage(at: index)
  445. // let newPage: CPDFPage = CPDFPage(image: NSImage(data: tiffData!))
  446. // newPage.setBounds(NSMakeRect(0, 0, pageSize.width, pageSize.height), for: .cropBox)
  447. // let result = self.preView.document.insertPageObject(newPage, at: index)
  448. let result = self.preView.document.insertPage(pageSize, at: index)
  449. // var newDoc = CPDFDocument()
  450. /// 刷新预览视图
  451. self.preView.layoutDocumentView()
  452. self.preView.displayBox = .cropBox
  453. }
  454. private func cropAllPate() {
  455. var size = NSZeroSize
  456. for i in 0 ..< self.preView.document.pageCount {
  457. let page = self.preView.document.page(at: i)
  458. var rect = getPageForegroundBox(page!)
  459. size.width = fmax(size.width, NSWidth(rect))
  460. size.height = fmax(size.height, NSHeight(rect))
  461. }
  462. var rectArray: Array<NSRect> = []
  463. for i in 0 ..< self.preView.document.pageCount {
  464. let page = self.preView.document.page(at: i)
  465. var rect = getPageForegroundBox(page!)
  466. var bounds: NSRect = (page?.bounds(for: .mediaBox))!
  467. if (rect.minX - bounds.minX > bounds.maxX-rect.maxX) {
  468. rect.origin.x = rect.maxX-size.width
  469. }
  470. rect.origin.y = rect.maxY-size.height
  471. rect.size = size
  472. if (NSWidth(rect) > NSWidth(bounds)) {
  473. rect.size.width = NSWidth(bounds)
  474. }
  475. if (NSHeight(rect) > NSHeight(bounds)) {
  476. rect.size.height = NSHeight(bounds)
  477. }
  478. if (NSMinX(rect) < NSMinX(bounds)) {
  479. rect.origin.x = NSMinX(bounds)
  480. } else if (NSMaxX(rect) > NSMaxX(bounds)) {
  481. rect.origin.x = NSMaxX(bounds) - NSWidth(rect)
  482. }
  483. if (NSMinY(rect) < NSMinY(bounds)) {
  484. rect.origin.y = NSMinY(bounds)
  485. } else if (NSMaxY(rect) > NSMaxY(bounds)) {
  486. rect.origin.y = NSMaxY(bounds) - NSHeight(rect)
  487. }
  488. rectArray.append(rect)
  489. }
  490. cropPages(to: rectArray)
  491. }
  492. private func cropPages(to rects: Array<NSRect>) {
  493. let currentPage = self.preView.currentPage()
  494. let visibleRect: NSRect = self.preView.convert(self.preView.convert(self.preView.documentView().visibleRect, from: self.preView.documentView()), to: self.preView.currentPage())
  495. var oldRectArray: Array<NSRect> = []
  496. for i in 0 ..< self.preView.document.pageCount {
  497. let page = self.preView.document.page(at: i)
  498. var rect = NSIntersectionRect(rects[Int(i)], (page?.bounds(for: .mediaBox))!)
  499. let oldRect = page?.bounds(for: .cropBox)
  500. oldRectArray.append(oldRect!)
  501. page?.setBounds(rect, for: .cropBox)
  502. }
  503. /// 刷新预览视图
  504. self.preView.layoutDocumentView()
  505. self.preView.displayBox = .cropBox
  506. self.preView.go(to: currentPage)
  507. self.preView.go(to: visibleRect, on: currentPage)
  508. }
  509. private func cropCurrentPage() {
  510. let myPreView: CPDFListView = self.preView as! CPDFListView
  511. var rect = NSIntegralRect(myPreView.currentSelectionRect())
  512. var page: CPDFPage?
  513. if ((myPreView.currentSelectionPage()) != nil) {
  514. page = myPreView.currentSelectionPage()
  515. } else {
  516. page = myPreView.currentPage()
  517. }
  518. if (NSIsEmptyRect(rect)) {
  519. rect = getPageForegroundBox(page!)
  520. }
  521. let index: UInt = (page?.pageIndex())!
  522. cropPage(at: index, in: rect)
  523. }
  524. func cropPage(at index: UInt, in rect: NSRect) {
  525. let oldRect = self.preView.document.page(at: index)?.bounds(for: .cropBox)
  526. /// undo \ redo 处理
  527. // NSUndoManager *undoManager = [[self document] undoManager];
  528. // let undoManager = UndoManager()
  529. // (undoManager.prepare(withInvocationTarget: self) as! KMCropPreviewController).cropPage(at: index, in: oldRect!)
  530. // undoManager.setActionName(NSLocalizedString("Crop Page", comment: "Undo action name"))
  531. // [[self document] undoableActionIsDiscardable];
  532. var page = self.preView.document.page(at: index)
  533. var newRect = NSIntersectionRect(rect, (page?.bounds(for: .mediaBox))!)
  534. page?.setBounds(newRect, for: .cropBox)
  535. /// 刷新预览视图
  536. self.preView.layoutDocumentView()
  537. self.preView.displayBox = .cropBox
  538. }
  539. private func getPageForegroundBox(_ page: CPDFPage) -> NSRect {
  540. let marginWidth: CGFloat = 10
  541. let marginHeight: CGFloat = 10
  542. let imageRep = newBitmapImageRepForBox(page, .mediaBox)
  543. let bounds = page.bounds(for: .mediaBox)
  544. var foregroundBox = imageRep.foregroundRect()
  545. if (imageRep == nil) {
  546. foregroundBox = bounds
  547. } else if (NSIsEmptyRect(foregroundBox)) {
  548. let centerPoint = NSPoint(x: bounds.midX, y: bounds.midY)
  549. let origin = NSPoint(x: round(centerPoint.x), y: round(centerPoint.y))
  550. foregroundBox.origin = origin
  551. foregroundBox.size = NSZeroSize
  552. } else {
  553. let origin = NSPoint(x: foregroundBox.origin.x+bounds.origin.x, y: foregroundBox.origin.y+bounds.origin.y)
  554. foregroundBox.origin = origin
  555. }
  556. return NSIntegralRect(NSInsetRect(foregroundBox, -marginWidth, -marginHeight))
  557. }
  558. private func newBitmapImageRepForBox(_ page: CPDFPage, _ box: CPDFDisplayBox) -> NSBitmapImageRep {
  559. let bounds = page.bounds(for: box)
  560. var imageRep = NSBitmapImageRep(bitmapDataPlanes: nil,
  561. pixelsWide: Int(NSWidth(bounds)),
  562. pixelsHigh: Int(NSHeight(bounds)),
  563. bitsPerSample: 8,
  564. samplesPerPixel: 4,
  565. hasAlpha: true,
  566. isPlanar: false,
  567. colorSpaceName: .calibratedRGB,
  568. bitmapFormat: NSBitmapImageRep.Format(rawValue: 0),
  569. bytesPerRow: 0,
  570. bitsPerPixel: 32)
  571. if (imageRep != nil) {
  572. NSGraphicsContext.saveGraphicsState()
  573. NSGraphicsContext.current = NSGraphicsContext.init(bitmapImageRep: imageRep!)
  574. NSGraphicsContext.current?.imageInterpolation = .none
  575. NSGraphicsContext.current?.shouldAntialias = false
  576. if (page.rotation != 0) {
  577. var transform = NSAffineTransform()
  578. if (page.rotation == 90) {
  579. transform.translateX(by: NSWidth(bounds), yBy: 0)
  580. } else if (page.rotation == 180) {
  581. transform.translateX(by: NSHeight(bounds), yBy: NSWidth(bounds))
  582. } else if (page.rotation == 270) {
  583. transform.translateX(by: 0, yBy: NSHeight(bounds))
  584. }
  585. transform.rotate(byDegrees: CGFloat(page.rotation))
  586. transform.concat()
  587. }
  588. page.draw(with: box, to: (NSGraphicsContext.current?.cgContext as! CGContext))
  589. // page.draw(with: box)
  590. NSGraphicsContext.current?.imageInterpolation = .default
  591. NSGraphicsContext.restoreGraphicsState()
  592. }
  593. return imageRep!
  594. }
  595. }
  596. extension KMCropPreviewController: CPDFViewDelegate {
  597. func pdfViewEditingSelectionDidChanged(_ pdfView: CPDFView!) {
  598. }
  599. }
  600. extension KMCropPreviewController: CPDFListViewDelegate {
  601. func pdfListViewDidSelectionEnd(_ pdfListView: CPDFListView!) {
  602. if (self.preView.isEqual(to: pdfListView)) {
  603. self.tipView.setString(string: "请按 Enter 键确定裁剪区域")
  604. }
  605. }
  606. }
  607. //extension PDFPage {
  608. // func getPageForegroundBox() -> NSRect {
  609. // let marginWidth: CGFloat = 10
  610. // let marginHeight: CGFloat = 10
  611. //
  612. // let imageRep = newBitmapImageRepForBox(.mediaBox)
  613. // let bounds = bounds(for: .mediaBox)
  614. // var foregroundBox = imageRep.foregroundRect()
  615. // if (imageRep == nil) {
  616. // foregroundBox = bounds
  617. // } else if (NSIsEmptyRect(foregroundBox)) {
  618. // let centerPoint = NSPoint(x: bounds.midX, y: bounds.midY)
  619. // let origin = NSPoint(x: round(centerPoint.x), y: round(centerPoint.y))
  620. // foregroundBox.origin = origin
  621. // foregroundBox.size = NSZeroSize
  622. // } else {
  623. // let origin = NSPoint(x: foregroundBox.origin.x+bounds.origin.x, y: foregroundBox.origin.y+bounds.origin.y)
  624. // foregroundBox.origin = origin
  625. // }
  626. //
  627. // return NSIntegralRect(NSInsetRect(foregroundBox, -marginWidth, -marginHeight))
  628. // }
  629. //
  630. // func newBitmapImageRepForBox(_ box: PDFDisplayBox) -> NSBitmapImageRep {
  631. // let bounds = bounds(for: box)
  632. // let imageRep = NSBitmapImageRep(bitmapDataPlanes: nil,
  633. // pixelsWide: Int(NSWidth(bounds)),
  634. // pixelsHigh: Int(NSHeight(bounds)),
  635. // bitsPerSample: 8,
  636. // samplesPerPixel: 4,
  637. // hasAlpha: true,
  638. // isPlanar: false,
  639. // colorSpaceName: .calibratedRGB,
  640. // bitmapFormat: NSBitmapImageRep.Format(rawValue: 0),
  641. // bytesPerRow: 0,
  642. // bitsPerPixel: 32)
  643. //
  644. // if (imageRep != nil) {
  645. // NSGraphicsContext.saveGraphicsState()
  646. // NSGraphicsContext.current = NSGraphicsContext.init(bitmapImageRep: imageRep!)
  647. // NSGraphicsContext.current?.imageInterpolation = .none
  648. // NSGraphicsContext.current?.shouldAntialias = false
  649. // if (self.rotation != 0) {
  650. // let transform = NSAffineTransform()
  651. // if (self.rotation == 90) {
  652. // transform.translateX(by: NSWidth(bounds), yBy: 0)
  653. // } else if (self.rotation == 180) {
  654. // transform.translateX(by: NSHeight(bounds), yBy: NSWidth(bounds))
  655. // } else if (self.rotation == 270) {
  656. // transform.translateX(by: 0, yBy: NSHeight(bounds))
  657. // }
  658. //
  659. // transform.rotate(byDegrees: CGFloat(self.rotation))
  660. // transform.concat()
  661. // }
  662. //
  663. // draw(with: box)
  664. // NSGraphicsContext.current?.imageInterpolation = .default
  665. // NSGraphicsContext.restoreGraphicsState()
  666. // }
  667. //
  668. // return imageRep!
  669. // }
  670. //}