KMWatermarkView.swift 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250
  1. //
  2. // KMWatermarkView.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by lizhe on 2023/11/14.
  6. //
  7. import Cocoa
  8. enum KMWatermarkManagerType {
  9. case add
  10. case edit
  11. case use
  12. }
  13. typealias KMWatermarkViewOperateCallBack = (_ watermark: KMWatermarkModel, _ countType: Int) -> ()
  14. typealias KMWatermarkViewCancelAction = (_ view: KMWatermarkView) -> Void
  15. class KMWatermarkView: KMBaseXibView, NSTextFieldDelegate, NSComboBoxDelegate, NSTextViewDelegate, CPDFViewDelegate {
  16. //顶部box
  17. @IBOutlet var typeBox: NSBox!
  18. @IBOutlet var txtButton: NSButton!
  19. @IBOutlet var fileButton: NSButton!
  20. @IBOutlet var filePathLabel: NSTextField!
  21. @IBOutlet var browsebutton: NSButton!
  22. @IBOutlet var ratioLabel: NSTextField!
  23. @IBOutlet var ratioTextField: NSTextField!
  24. @IBOutlet var ratioStepper: NSStepper!
  25. @IBOutlet var fontLabel: NSTextField!
  26. @IBOutlet var fontComboBox: NSComboBox!
  27. @IBOutlet var fontSizeLabel: NSTextField!
  28. @IBOutlet var fontSizeCombobox: NSComboBox!
  29. @IBOutlet var colorLabel: NSTextField!
  30. @IBOutlet var colorWell: NSColorWell!
  31. @IBOutlet var watermarkStringTextView: NSTextView!
  32. var maskView: KMBookletMaskView?
  33. //底部box
  34. @IBOutlet var appearanceBox: NSBox!
  35. @IBOutlet var angleLabel: NSTextField!
  36. @IBOutlet var angleTextF: NSTextField!
  37. @IBOutlet var angleStepper: NSStepper!
  38. @IBOutlet var left45IndicateView: KMAngleIndicateView!
  39. @IBOutlet var horizontalIndicateView: KMAngleIndicateView!
  40. @IBOutlet var right45IndicateView: KMAngleIndicateView!
  41. @IBOutlet var alphaLabel: NSTextField!
  42. @IBOutlet var alphaSlider: NSSlider!
  43. @IBOutlet var alphaTextField: NSTextField!
  44. @IBOutlet var alphaStepper: NSStepper!
  45. @IBOutlet var watermarkPositionLabel: NSTextField!
  46. @IBOutlet var OnPageButton: NSButton!
  47. @IBOutlet var backPageButton: NSButton!
  48. @IBOutlet var positionView: KMPostionIndicateView!
  49. @IBOutlet var horizentalGapLabel: NSTextField!
  50. @IBOutlet var verticalGapLabel: NSTextField!
  51. @IBOutlet var horizentalGapTextField: NSTextField!
  52. @IBOutlet var verticalFapTextField: NSTextField!
  53. @IBOutlet var horizentalGapStepper: NSStepper!
  54. @IBOutlet var verticalGapStepper: NSStepper!
  55. @IBOutlet var pageRangeLabel: NSTextField!
  56. @IBOutlet var pageRangeComboBox: NSComboBox!
  57. //保存到模版按钮
  58. @IBOutlet var saveToTemplateButton: NSButton!
  59. @IBOutlet var templateNameLabel: NSTextField!
  60. @IBOutlet var templateNameTextField: NSTextField!
  61. @IBOutlet var isTileWater: NSButton!
  62. @IBOutlet var spacingHorTextField: NSTextField!
  63. @IBOutlet var spacingHorStepper: NSStepper!
  64. @IBOutlet var horizentalIconButton: NSButton!
  65. @IBOutlet var verticalIconButton: NSButton!
  66. @IBOutlet var spacingVerTextField: NSTextField!
  67. @IBOutlet var spacingStepper: NSStepper!
  68. //底部按钮
  69. @IBOutlet var batchButton: NSButton!
  70. @IBOutlet var cancelButton: NSButton!
  71. @IBOutlet var applyButton: NSButton!
  72. //左侧
  73. @IBOutlet var previewPageButton: NSButton!
  74. @IBOutlet var nextPageButton: NSButton!
  75. @IBOutlet var currentPageIndexTextF: NSTextField!
  76. @IBOutlet var totalPageCountLabel: NSTextField!
  77. @IBOutlet var pdfView: KMWatermarkPDFView!
  78. var fontModified: Bool = false
  79. var currentType: Int = 0
  80. var filePath: String = Bundle.main.path(forResource: "Quick Start Guide", ofType: "pdf") ?? ""
  81. var password: String = ""
  82. var originalWatermark: KMWatermarkModel = KMWatermarkModel()
  83. var watermark: KMWatermarkModel = KMWatermarkModel()
  84. var type: KMWatermarkManagerType = .use {
  85. didSet {
  86. if type == .edit {
  87. } else {
  88. watermark.watermarkID = KMWatermarkManager.defaultManager.fetchAvailableName()
  89. }
  90. self.templateNameTextField.stringValue = self.watermark.watermarkID
  91. }
  92. }
  93. var pdfDocument: CPDFDocument? {
  94. didSet {
  95. self._fileAttri = KMFileAttribute()
  96. self._fileAttri?.password = self.pdfDocument?.password ?? ""
  97. self._fileAttri?.filePath = self.pdfDocument?.documentURL?.path ?? ""
  98. self.password = pdfDocument?.password ?? ""
  99. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
  100. self.pdfView.watermark = self.watermark
  101. self.pdfView.document = self.pdfDocument
  102. self.pdfView.autoScales = true
  103. self.pdfView.documentView().enclosingScrollView?.scrollerStyle = .overlay
  104. self.pdfView.documentView().enclosingScrollView?.hasVerticalScroller = false
  105. self.pdfView.documentView().enclosingScrollView?.hasHorizontalScroller = false
  106. }
  107. // self.reloadData()
  108. }
  109. }
  110. var onlyManagerTemplate: Bool = true
  111. var isHiddenBatchBtn: Bool = false
  112. private var _fileAttri: KMFileAttribute?
  113. var cancelAction: KMWatermarkViewCancelAction?
  114. var operateCallBack: KMWatermarkViewOperateCallBack?
  115. convenience init(baseFile filePath: String, watermark: KMWatermarkModel, password: String, type: KMWatermarkManagerType, fileType countType: Int) {
  116. self.init()
  117. self.filePath = filePath
  118. self.password = password
  119. self.originalWatermark = watermark.copy() as! KMWatermarkModel
  120. self.watermark = watermark.copy() as! KMWatermarkModel
  121. self.type = type
  122. self.pdfDocument = CPDFDocument(url: URL(fileURLWithPath: self.filePath))
  123. self.currentType = countType
  124. if pdfDocument?.isLocked ?? false {
  125. pdfDocument?.unlock(withPassword: password)
  126. }
  127. }
  128. override func setup() {
  129. pdfView.setDisplay(.singlePage)
  130. // if (pdfView.documentView() != nil) {
  131. // pdfView.setDisplay(.singlePage)
  132. // pdfView.documentView().enclosingScrollView?.scrollerStyle = .overlay
  133. // pdfView.documentView().enclosingScrollView?.hasVerticalScroller = false
  134. // pdfView.documentView().enclosingScrollView?.hasHorizontalScroller = false
  135. // }
  136. for i in 0..<3 {
  137. for j in 0..<3 {
  138. if i == Int(watermark.horizontalMode) && j == Int(watermark.verticalMode) {
  139. positionView.style = KMPositionIndicateViewStyle(rawValue: i + 3 * j)!
  140. }
  141. }
  142. }
  143. positionView.styleChangedCallBack = { [weak self] in
  144. guard let self = self else { return }
  145. self.watermark.horizontalMode = self.positionView.style.rawValue % 3
  146. self.watermark.verticalMode = self.positionView.style.rawValue / 3
  147. self.updatePDFView()
  148. }
  149. currentPageIndexTextF.stringValue = "1"
  150. // let numberFormatter = currentPageIndexTextF.formatter as! NumberFormatter
  151. // numberFormatter.maximum = NSNumber(value: pdfDocument!.pageCount)
  152. pdfView.delegate = self
  153. left45IndicateView.style = .left45
  154. left45IndicateView.touchCallBack = { [weak self] in
  155. guard let self = self else { return }
  156. self.watermark.rotation = -45
  157. self.angleStepper.doubleValue = self.watermark.rotation
  158. self.angleTextF.stringValue = "\(self.angleStepper.intValue)"
  159. self.checkAngle()
  160. self.updatePDFView()
  161. }
  162. horizontalIndicateView.style = .horizontal
  163. horizontalIndicateView.touchCallBack = { [weak self] in
  164. guard let self = self else { return }
  165. self.watermark.rotation = 0
  166. self.angleStepper.doubleValue = 0
  167. self.angleTextF.stringValue = "\(0)"
  168. self.checkAngle()
  169. self.updatePDFView()
  170. }
  171. right45IndicateView.style = .right45
  172. right45IndicateView.touchCallBack = { [weak self] in
  173. guard let self = self else { return }
  174. self.watermark.rotation = 45
  175. self.angleStepper.doubleValue = self.watermark.rotation
  176. self.angleTextF.stringValue = "\(self.angleStepper.intValue)"
  177. self.checkAngle()
  178. self.updatePDFView()
  179. }
  180. saveToTemplateButton.isEnabled = onlyManagerTemplate
  181. // if type == .use {
  182. // saveToTemplateButton.isHidden = true
  183. // saveToTemplateButton.state = .off
  184. // } else {
  185. // saveToTemplateButton.isHidden = false
  186. // saveToTemplateButton.state = .on
  187. // }
  188. if type == .add {
  189. applyButton.title = NSLocalizedString("Apply", comment: "")
  190. batchButton.isHidden = true
  191. } else if type == .edit {
  192. applyButton.title = NSLocalizedString("Apply", comment: "")
  193. batchButton.isHidden = true
  194. } else if type == .use {
  195. applyButton.title = NSLocalizedString("Save & Apply", comment: "")
  196. }
  197. filePathLabel.stringValue = ""
  198. filePathLabel.placeholderString = NSLocalizedString("Select a File", comment: "")
  199. fontSizeCombobox.removeAllItems()
  200. fontSizeCombobox.addItems(withObjectValues: ["9","10","11","12","13","14","18","24","36","48","64","72","96","144","288"])
  201. fontSizeCombobox.formatter = TextFieldFormatter()
  202. watermarkStringTextView.delegate = self
  203. pageRangeComboBox.removeAllItems()
  204. pageRangeComboBox.addItems(withObjectValues: [
  205. NSLocalizedString("All Pages", comment: ""),
  206. NSLocalizedString("Odd Pages Only", comment: ""),
  207. NSLocalizedString("Even Pages Only", comment: ""),
  208. NSLocalizedString("e.g. 1,3-5,10", comment: "")
  209. ])
  210. pageRangeComboBox.placeholderString = NSLocalizedString("e.g. 1,3-5,10", comment: "")
  211. pageRangeComboBox.delegate = nil
  212. pageRangeComboBox.selectItem(at: 0)
  213. pageRangeComboBox.isEditable = false
  214. pageRangeComboBox.delegate = self
  215. fontSizeCombobox.wantsLayer = true
  216. pageRangeComboBox.wantsLayer = true
  217. fontSizeCombobox.layer?.cornerRadius = 3.0
  218. pageRangeComboBox.layer?.cornerRadius = 3.0
  219. self.verticalFapTextField.delegate = self
  220. self.horizentalGapTextField.delegate = self
  221. self.spacingHorTextField.delegate = self
  222. self.spacingVerTextField.delegate = self
  223. }
  224. override func updateLanguage() {
  225. typeBox.title = NSLocalizedString("Source", comment: "")
  226. typeBox.titleFont = NSFont.systemFont(ofSize: 13)
  227. txtButton.title = NSLocalizedString("Text", comment: "")
  228. fileButton.title = NSLocalizedString("File", comment: "")
  229. browsebutton.title = NSLocalizedString("Choose...", comment: "")
  230. ratioLabel.stringValue = "\(NSLocalizedString("Ratio", comment: "")):"
  231. fontLabel.stringValue = NSLocalizedString("Font", comment: "")
  232. horizentalIconButton.toolTip = NSLocalizedString("Horizontal Distance", comment: "")
  233. verticalIconButton.toolTip = NSLocalizedString("Vertical Distance", comment: "")
  234. fontSizeLabel.stringValue = "\(NSLocalizedString("Font Size", comment: "")):"
  235. colorLabel.stringValue = "\(NSLocalizedString("Color", comment: "")):"
  236. templateNameTextField.stringValue = watermark.watermarkID ?? ""
  237. appearanceBox.title = NSLocalizedString("Appearance", comment: "")
  238. appearanceBox.titleFont = NSFont.systemFont(ofSize: 13)
  239. angleLabel.stringValue = "\(NSLocalizedString("Rotation", comment: "")):"
  240. alphaLabel.stringValue = "\(NSLocalizedString("Opacity", comment: "")):"
  241. watermarkPositionLabel.stringValue = "\(NSLocalizedString("Position", comment: "")):"
  242. OnPageButton.title = NSLocalizedString("Appear on top of page", comment: "")
  243. backPageButton.title = NSLocalizedString("Appear behind page", comment: "")
  244. pageRangeLabel.stringValue = "\(NSLocalizedString("Page Range", comment: "")):"
  245. isTileWater.title = NSLocalizedString("Tile", comment: "")
  246. OnPageButton.toolTip = NSLocalizedString("Appear on top of page", comment: "")
  247. backPageButton.toolTip = NSLocalizedString("Appear behind page", comment: "")
  248. pageRangeLabel.toolTip = "\(NSLocalizedString("Page Range", comment: "")):"
  249. horizentalGapLabel.stringValue = "X:"
  250. verticalGapLabel.stringValue = "Y:"
  251. saveToTemplateButton.title = NSLocalizedString("Add to Template", comment: "")
  252. templateNameLabel.stringValue = NSLocalizedString("Name:", comment: "")
  253. batchButton.title = NSLocalizedString("Batch", comment: "")
  254. cancelButton.title = NSLocalizedString("Cancel", comment: "")
  255. }
  256. override func reloadData() {
  257. guard let pdfDocument = pdfDocument else { return }
  258. let opacity = round(watermark.opacity * 100) / 100
  259. watermarkStringTextView.string = watermark.text
  260. colorWell.color = watermark.getTextColor()
  261. totalPageCountLabel.stringValue = "/ \(pdfDocument.pageCount)"
  262. fontSizeCombobox.stringValue = "\(Int(watermark.getTextFontSize()))"
  263. angleStepper.doubleValue = Double(watermark.rotation)
  264. angleTextF.stringValue = "\(angleStepper.doubleValue)"
  265. OnPageButton.state = watermark.isFront ? .on : .off
  266. backPageButton.state = watermark.isFront ? .off : .on
  267. alphaSlider.doubleValue = watermark.opacity
  268. alphaStepper.doubleValue = watermark.opacity
  269. alphaTextField.stringValue = "\(Int(opacity * 100))%"
  270. ratioStepper.doubleValue = watermark.scale
  271. ratioTextField.stringValue = "\(Int(opacity * 100))%"
  272. fontComboBox.stringValue = "\(watermark.getTextFontSize() )"
  273. filePathLabel.stringValue = watermark.imagePath
  274. batchButton.isHidden = isHiddenBatchBtn
  275. if !isHiddenBatchBtn {
  276. self.batchButton.isHidden = type != .use
  277. }
  278. if currentType == 0 {
  279. changeTypeBoxState(isTextWatermark: true)
  280. } else {
  281. changeTypeBoxState(isTextWatermark: false)
  282. }
  283. switch watermark.pageRangeType {
  284. case .all:
  285. pageRangeComboBox.isEditable = false
  286. pageRangeComboBox.selectItem(at: 0)
  287. case .odd:
  288. pageRangeComboBox.isEditable = false
  289. pageRangeComboBox.selectItem(at: 1)
  290. case .even:
  291. pageRangeComboBox.isEditable = false
  292. pageRangeComboBox.selectItem(at: 2)
  293. case .other:
  294. pageRangeComboBox.isEditable = true
  295. pageRangeComboBox.selectItem(at: 3)
  296. pageRangeComboBox.stringValue = watermark.pagesString
  297. }
  298. for i in 0..<3 {
  299. for j in 0..<3 {
  300. if i == Int(watermark.horizontalMode) && j == Int(watermark.verticalMode) {
  301. self.positionView.style = KMPositionIndicateViewStyle(rawValue: i + 3 * j)!
  302. }
  303. }
  304. }
  305. verticalGapStepper.doubleValue = Double(watermark.verticalSpace)
  306. verticalFapTextField.stringValue = "\(verticalGapStepper.doubleValue)"
  307. horizentalGapStepper.doubleValue = Double(watermark.horizontalSpace)
  308. horizentalGapTextField.stringValue = "\(horizentalGapStepper.doubleValue)"
  309. spacingHorTextField.stringValue = "\(watermark.tileHorizontalSpace)"
  310. spacingVerTextField.stringValue = "\(watermark.tileVerticalSpace)"
  311. spacingHorStepper.doubleValue = Double(watermark.tileHorizontalSpace)
  312. spacingStepper.doubleValue = Double(watermark.tileVerticalSpace)
  313. if watermark.isTilePage {
  314. isTileWater.state = .on
  315. spacingHorTextField.isEnabled = true
  316. spacingHorStepper.isEnabled = true
  317. spacingVerTextField.isEnabled = true
  318. spacingStepper.isEnabled = true
  319. } else {
  320. isTileWater.state = .off
  321. spacingHorTextField.isEnabled = false
  322. spacingHorStepper.isEnabled = false
  323. spacingVerTextField.isEnabled = false
  324. spacingStepper.isEnabled = false
  325. }
  326. pageRangeComboxAction(Any.self)
  327. checkAngle()
  328. }
  329. override func addNotification() {
  330. NotificationCenter.default.addObserver(self, selector: #selector(pageChangeNotification), name: NSNotification.Name.CPDFViewPageChanged, object: self.pdfView)
  331. }
  332. func updatePDFView() {
  333. // pdfView.needsDisplay = true
  334. km_synchronized(self) {
  335. self.pdfView.setNeedsDisplayForVisiblePages()
  336. }
  337. }
  338. func checkAngle() {
  339. left45IndicateView.isSelcted = false
  340. horizontalIndicateView.isSelcted = false
  341. right45IndicateView.isSelcted = false
  342. switch watermark.rotation {
  343. case -45:
  344. left45IndicateView.isSelcted = true
  345. case 0:
  346. horizontalIndicateView.isSelcted = true
  347. case 45:
  348. right45IndicateView.isSelcted = true
  349. default:
  350. break
  351. }
  352. }
  353. func changeTypeBoxState(isTextWatermark: Bool) {
  354. if isTextWatermark {
  355. txtButton.state = .on
  356. watermarkStringTextView.isEditable = true
  357. watermarkStringTextView.isSelectable = true
  358. fontSizeCombobox.isEnabled = true
  359. colorWell.isEnabled = true
  360. fileButton.state = .off
  361. browsebutton.isEnabled = false
  362. ratioTextField.isEnabled = false
  363. ratioStepper.isEnabled = false
  364. watermark.text = watermarkStringTextView.string
  365. watermarkStringTextView.string = watermarkStringTextView.string
  366. watermark.image = nil
  367. if watermarkStringTextView.string.isEmpty == false {
  368. applyButton.isEnabled = true
  369. batchButton.isEnabled = true
  370. } else {
  371. applyButton.isEnabled = false
  372. batchButton.isEnabled = false
  373. }
  374. } else {
  375. txtButton.state = .off
  376. watermarkStringTextView.isEditable = false
  377. watermarkStringTextView.isSelectable = false
  378. fontSizeCombobox.isEnabled = false
  379. colorWell.isEnabled = false
  380. fileButton.state = .on
  381. browsebutton.isEnabled = true
  382. ratioTextField.isEnabled = true
  383. ratioStepper.isEnabled = true
  384. watermark.text = ""
  385. if let _image = NSImage(contentsOfFile: watermark.imagePath ) {
  386. watermark.image = _image
  387. }
  388. if filePathLabel.stringValue.isEmpty == false {
  389. applyButton.isEnabled = true
  390. batchButton.isEnabled = true
  391. } else {
  392. applyButton.isEnabled = false
  393. batchButton.isEnabled = false
  394. }
  395. }
  396. updatePDFView()
  397. }
  398. func checkPageRangeValidate(_ pageRangeString: String) -> Bool {
  399. var fileAttribute = self._fileAttri
  400. if fileAttribute == nil {
  401. fileAttribute = KMFileAttribute()
  402. fileAttribute?.password = self.pdfDocument?.password ?? ""
  403. fileAttribute?.filePath = self.pdfDocument?.documentURL.path ?? ""
  404. self._fileAttri = fileAttribute
  405. }
  406. fileAttribute?.bAllPage = false
  407. fileAttribute?.pagesString = self.pageRangeComboBox.stringValue
  408. var pageRange: KMPageRange = .all
  409. let pageRangeType: KMWatermarkeModelPageRangeType = watermark.pageRangeType
  410. if pageRangeType == .all {
  411. pageRange = .all
  412. } else if pageRangeType == .even {
  413. pageRange = .even
  414. } else if pageRangeType == .odd {
  415. pageRange = .odd
  416. } else if pageRangeType == .other {
  417. pageRange = .custom
  418. }
  419. fileAttribute?.pagesType = pageRange
  420. if let cnt = fileAttribute?.fetchSelectPages().count, cnt == 0 {
  421. return false
  422. }
  423. return true
  424. }
  425. @objc func controlTextDidEndEditing(_ obj: Notification) {
  426. if obj.object as? NSComboBox == self.fontSizeCombobox {
  427. var textSize = CGFloat(Int(self.fontSizeCombobox.stringValue) ?? 0)
  428. if textSize == 0 {
  429. textSize = 48
  430. if self.watermark.isTilePage {
  431. textSize = 18
  432. }
  433. }
  434. self.watermark.textFont = KMWatermarkAdjectiveText.font(name: "Helvetica", size: textSize)
  435. self.fontSizeCombobox.stringValue = "\(Int(textSize))"
  436. self.updatePDFView()
  437. } else if obj.object as? NSTextField == self.ratioTextField {
  438. let formatter = self.ratioTextField.formatter as? NumberFormatter
  439. _ = formatter?.number(from: self.ratioTextField.stringValue)?.floatValue ?? 0
  440. self.ratioStepper.doubleValue = Double(self.watermark.scale)
  441. self.updatePDFView()
  442. } else if obj.object as? NSTextField == self.angleTextF {
  443. self.watermark.rotation = CGFloat(Int(self.angleTextF.stringValue) ?? 0)
  444. self.angleStepper.doubleValue = self.watermark.rotation
  445. self.checkAngle()
  446. self.updatePDFView()
  447. } else if obj.object as? NSTextField == self.alphaTextField {
  448. let formatter = self.alphaTextField.formatter as? NumberFormatter
  449. _ = formatter?.number(from: self.alphaTextField.stringValue)?.floatValue ?? 0
  450. self.alphaSlider.doubleValue = Double(self.watermark.opacity)
  451. self.alphaStepper.doubleValue = Double(self.watermark.opacity)
  452. self.updatePDFView()
  453. } else if obj.object as? NSComboBox == self.pageRangeComboBox {
  454. if self.pageRangeComboBox.indexOfSelectedItem == -1 {
  455. if !self.checkPageRangeValidate(self.pageRangeComboBox.stringValue) {
  456. let alert = NSAlert()
  457. alert.alertStyle = .critical
  458. alert.messageText = "\(String(describing: self.pdfDocument?.documentURL.lastPathComponent)) \(NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: ""))"
  459. alert.runModal()
  460. self.window?.makeFirstResponder(self.pageRangeComboBox)
  461. return
  462. } else {
  463. self.watermark.pagesString = self.pageRangeComboBox.stringValue
  464. self.updatePDFView()
  465. }
  466. }
  467. } else if obj.object as? NSTextField == self.verticalFapTextField {
  468. self.watermark.verticalSpace = CGFloat(Int(self.verticalFapTextField.stringValue) ?? 0)
  469. self.verticalGapStepper.doubleValue = Double(self.watermark.verticalSpace)
  470. self.updatePDFView()
  471. } else if obj.object as? NSTextField == self.horizentalGapTextField {
  472. self.watermark.horizontalSpace = CGFloat(Int(self.horizentalGapTextField.stringValue) ?? 0)
  473. self.horizentalGapStepper.doubleValue = Double(self.watermark.horizontalSpace)
  474. self.updatePDFView()
  475. } else if obj.object as? NSTextField == self.currentPageIndexTextF {
  476. self.pdfView.go(toPageIndex: (Int(self.currentPageIndexTextF.stringValue) ?? 0 - 1), animated: false)
  477. } else if obj.object as? NSTextField == self.spacingHorTextField {
  478. self.watermark.tileHorizontalSpace = CGFloat(Int(self.spacingHorTextField.stringValue) ?? 0)
  479. self.spacingHorStepper.doubleValue = Double(self.watermark.tileHorizontalSpace)
  480. self.updatePDFView()
  481. } else if obj.object as? NSTextField == self.spacingVerTextField {
  482. self.watermark.tileVerticalSpace = CGFloat(Int(self.spacingVerTextField.stringValue) ?? 0)
  483. self.spacingStepper.doubleValue = Double(self.watermark.tileVerticalSpace)
  484. self.updatePDFView()
  485. }
  486. }
  487. @objc func comboBoxSelectionDidChange(_ notification: Notification) {
  488. if notification.object as? NSComboBox == self.pageRangeComboBox {
  489. self.pageRangeComboBox.isEditable = false
  490. if self.pageRangeComboBox.indexOfSelectedItem == 0 {
  491. self.watermark.pageRangeType = .all
  492. } else if self.pageRangeComboBox.indexOfSelectedItem == 1 {
  493. self.watermark.pageRangeType = .odd
  494. } else if self.pageRangeComboBox.indexOfSelectedItem == 2 {
  495. self.watermark.pageRangeType = .even
  496. } else {
  497. self.watermark.pageRangeType = .other
  498. self.pageRangeComboBox.stringValue = ""
  499. self.pageRangeComboBox.isEditable = true
  500. self.window?.makeFirstResponder(self.pageRangeComboBox)
  501. }
  502. }
  503. }
  504. @objc func textDidChange(_ notification: Notification) {
  505. if notification.object as? NSTextView == self.watermarkStringTextView {
  506. self.watermark.text = self.watermarkStringTextView.string
  507. self.applyButton.isEnabled = !self.watermark.text.isEmpty
  508. self.batchButton.isEnabled = !self.watermark.text.isEmpty
  509. self.updatePDFView()
  510. }
  511. }
  512. func isDamageImage(_ image: NSImage?, imagePath path: String) -> Bool {
  513. let addImageAnnotation = (NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).last! as NSString).appendingPathComponent(Bundle.main.bundleIdentifier!)
  514. if !FileManager.default.fileExists(atPath: addImageAnnotation) {
  515. try? FileManager.default.createDirectory(atPath: addImageAnnotation, withIntermediateDirectories: false, attributes: nil)
  516. }
  517. let data = image?.tiffRepresentation
  518. let imageRep = NSBitmapImageRep(data: data!)
  519. imageRep?.size = image?.size ?? NSSize.zero
  520. var imageData: Data?
  521. if path.lowercased() == "png" {
  522. imageData = imageRep?.representation(using: .png, properties: [:])
  523. } else {
  524. imageData = imageRep?.representation(using: .jpeg, properties: [:])
  525. }
  526. let rPath = (addImageAnnotation as NSString).appendingPathComponent("waterAnnotation.png")
  527. if ((try? imageData?.write(to: URL(fileURLWithPath: rPath), options: .atomic)) == nil) {
  528. return true
  529. } else {
  530. return false
  531. }
  532. }
  533. func tagString() -> String {
  534. let dateFormatter = DateFormatter()
  535. dateFormatter.dateFormat = "yyMMddHHmmss"
  536. return "\(dateFormatter.string(from: Date()))\(arc4random() % 10000)"
  537. }
  538. // MARK: - Action
  539. // NSNotification
  540. @objc func pageChangeNotification(_ notification: Notification) {
  541. currentPageIndexTextF.stringValue = "\(pdfView.currentPage().pageIndex() + 1)"
  542. }
  543. // 开始转圈,隐藏转圈提示
  544. func showWaitting() {
  545. if maskView == nil {
  546. maskView = KMBookletMaskView(frame: NSRect(x: 0, y: 0, width: window?.frame.size.width ?? 0, height: window?.frame.size.height ?? 0))
  547. }
  548. window?.contentView?.addSubview(maskView!)
  549. }
  550. func hideWaitting() {
  551. maskView?.removeFromSuperview()
  552. }
  553. override func mouseDown(with event: NSEvent) {
  554. super.mouseDown(with: event)
  555. window?.makeFirstResponder(nil)
  556. }
  557. }
  558. extension KMWatermarkView {
  559. @IBAction func buttonClicked_SwitchTextWatermark(_ sender: Any) {
  560. currentType = 0
  561. changeTypeBoxState(isTextWatermark: true)
  562. }
  563. @IBAction func buttonClicked_SwitchFileWaterMark(_ sender: Any) {
  564. currentType = 1
  565. changeTypeBoxState(isTextWatermark: false)
  566. }
  567. @IBAction func buttonClicked_BrowseFile(_ sender: Any) {
  568. let openPanel = NSOpenPanel()
  569. openPanel.canChooseDirectories = false
  570. openPanel.canChooseFiles = true
  571. openPanel.allowsMultipleSelection = false
  572. openPanel.allowedFileTypes = ["jpg", "jpeg", "png", "pdf"]
  573. openPanel.beginSheetModal(for: window!) { (result) in
  574. if result == NSApplication.ModalResponse.OK {
  575. guard let url = openPanel.url else { return }
  576. let filePath = url.path
  577. if filePath.extension.lowercased() == ".pdf" {
  578. let pdf = CPDFDocument(url: url)
  579. guard !pdf!.isEncrypted else { return }
  580. self.showWaitting()
  581. let convert = KMPDFConvert()
  582. convert.convertType = .png
  583. convert.filePath = url.path
  584. convert.pages = [1]
  585. convert.outputFolderPath = (NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).last! as NSString).appendingPathComponent(Bundle.main.bundleIdentifier!)
  586. convert.outputFileName = "pdfConvertPng"
  587. KMPDFConvertManager.defaultManager.convert(convert: convert, completion: { (finished, error) in
  588. self.hideWaitting()
  589. if finished {
  590. let outputFilePath = convert.outputFilePath
  591. if FileManager.default.fileExists(atPath: outputFilePath) {
  592. let fimagePath = (try? FileManager.default.subpaths(atPath: outputFilePath))?.first
  593. let pdfPath = convert.outputFilePath + "/" + fimagePath!
  594. var newPath = (convert.outputFolderPath as NSString).appendingPathComponent(self.tagString())
  595. newPath = (newPath as NSString).appendingPathComponent(((url.path as NSString).lastPathComponent as NSString).deletingPathExtension + ".png")
  596. do {
  597. try FileManager.default.copyItem(atPath: pdfPath, toPath: newPath)
  598. try FileManager.default.removeItem(atPath: convert.outputFilePath)
  599. } catch {
  600. print(error.localizedDescription)
  601. }
  602. let image = NSImage(contentsOfFile: pdfPath)
  603. if self.isDamageImage(image, imagePath: pdfPath) {
  604. let alert = NSAlert()
  605. alert.alertStyle = .critical
  606. alert.messageText = "The file \"\(url.lastPathComponent)\" could not be opened."
  607. alert.informativeText = "It may be damaged or use a file format that PDF Reader Pro doesn’t recognize."
  608. alert.addButton(withTitle: "Cancel")
  609. alert.beginSheetModal(for: NSApp.mainWindow!) { (response) in
  610. if response == NSApplication.ModalResponse.alertFirstButtonReturn {
  611. // Cancel button clicked
  612. }
  613. }
  614. return
  615. }
  616. self.filePathLabel.stringValue = url.path
  617. self.watermark.imagePath = pdfPath
  618. self.watermark.image = NSImage(contentsOfFile: pdfPath)
  619. self.watermark.text = ""
  620. self.templateNameTextField.stringValue = self.watermark.watermarkID
  621. self.applyButton.isEnabled = true
  622. self.batchButton.isEnabled = true
  623. self.pdfView.setNeedsDisplay(NSRect.zero)
  624. }
  625. }
  626. })
  627. } else {
  628. let image = NSImage(contentsOfFile: url.path)
  629. if self.isDamageImage(image, imagePath: url.path) {
  630. let alert = NSAlert()
  631. alert.alertStyle = .critical
  632. alert.messageText = "The file \"\(url.lastPathComponent)\" could not be opened."
  633. alert.informativeText = "It may be damaged or use a file format that PDF Reader Pro doesn’t recognize."
  634. alert.addButton(withTitle: "Cancel")
  635. alert.beginSheetModal(for: NSApp.mainWindow!) { (response) in
  636. if response == NSApplication.ModalResponse.alertFirstButtonReturn {
  637. // Cancel button clicked
  638. }
  639. }
  640. return
  641. }
  642. self.filePathLabel.stringValue = url.path
  643. self.watermark.imagePath = url.path
  644. self.watermark.image = NSImage(contentsOfFile: url.path)
  645. self.watermark.text = ""
  646. self.templateNameTextField.stringValue = self.watermark.watermarkID
  647. self.applyButton.isEnabled = true
  648. self.batchButton.isEnabled = true
  649. self.pdfView.setNeedsDisplay(NSRect.zero)
  650. }
  651. }
  652. }
  653. }
  654. @IBAction func buttonClicked_Batch(_ sender: Any) {
  655. let needSave = saveToTemplateButton.state == .on
  656. if needSave {
  657. if templateNameTextField.stringValue.isEmpty {
  658. self.watermark.watermarkID = templateNameTextField.stringValue
  659. } else {
  660. self.watermark.watermarkID = KMWatermarkManager.defaultManager.fetchAvailableName()
  661. }
  662. let result = KMWatermarkManager.defaultManager.addWatermark(watermark: self.watermark)
  663. if !result {
  664. return
  665. }
  666. }
  667. if let operateCallBack = self.operateCallBack {
  668. operateCallBack(self.watermark, currentType)
  669. }
  670. // self.cancelAction?(self)
  671. }
  672. @IBAction func buttonClicked_Cancel(_ sender: Any) {
  673. self.pdfView.watermark = nil
  674. self.pdfView.background = nil
  675. self.pdfView.headerFooter = nil
  676. self.cancelAction?(self)
  677. }
  678. @IBAction func buttonClicked_Done(_ sender: Any) {
  679. guard let pdfDocument = pdfDocument else { return }
  680. if self.watermark.imagePath.count == 0 {
  681. if self.watermark.text.isEmpty {
  682. return
  683. }
  684. }
  685. if checkPageRangeValidate(pageRangeComboBox.stringValue) {
  686. watermark.pagesString = pageRangeComboBox.stringValue
  687. self.updatePDFView()
  688. window?.makeFirstResponder(self)
  689. }
  690. let needSave = saveToTemplateButton.state == .on
  691. var pages = [Int]()
  692. switch pageRangeComboBox.indexOfSelectedItem {
  693. case 0:
  694. pages = Array(0..<Int(pdfDocument.pageCount))
  695. case 1:
  696. pages = Array(stride(from: 0, to: Int(pdfDocument.pageCount), by: 2))
  697. case 2:
  698. pages = Array(stride(from: 1, to: Int(pdfDocument.pageCount), by: 2))
  699. default:
  700. var fileAttribute = self._fileAttri
  701. if fileAttribute == nil {
  702. fileAttribute = KMFileAttribute()
  703. fileAttribute?.password = pdfDocument.password ?? ""
  704. fileAttribute?.filePath = pdfDocument.documentURL?.path ?? ""
  705. self._fileAttri = fileAttribute
  706. }
  707. fileAttribute?.bAllPage = false
  708. fileAttribute?.pagesType = .custom
  709. fileAttribute?.pagesString = pageRangeComboBox.stringValue
  710. let selectPages = fileAttribute?.fetchSelectPages() ?? []
  711. if selectPages.count != 0 {
  712. pages = selectPages.map { $0 - 1 }
  713. } else {
  714. let alert = NSAlert()
  715. alert.alertStyle = .critical
  716. alert.messageText = "\(fileAttribute?.filePath.lastPathComponent ?? "") \(NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: ""))"
  717. alert.runModal()
  718. return
  719. }
  720. }
  721. watermark.pagesString = pages.isEmpty ? "" : pages.map { "\($0)" }.joined(separator: ",")
  722. if needSave {
  723. if self.templateNameTextField.stringValue.isEmpty {
  724. self.watermark.watermarkID = KMWatermarkManager.defaultManager.fetchAvailableName()
  725. } else {
  726. self.watermark.watermarkID = self.templateNameTextField.stringValue
  727. }
  728. if KMWatermarkManager.defaultManager.watermarks.contains(self.originalWatermark) {
  729. let _ = KMWatermarkManager.defaultManager.removeWatermark(watermark: self.originalWatermark)
  730. let _ = KMWatermarkManager.defaultManager.addWatermark(watermark: self.watermark)
  731. } else {
  732. let _ = KMWatermarkManager.defaultManager.addWatermark(watermark: self.watermark)
  733. }
  734. }
  735. if self.type == .edit || self.type == .add {
  736. if let operateCallBack = self.operateCallBack {
  737. operateCallBack(self.watermark, currentType)
  738. }
  739. self.cancelAction?(self)
  740. } else if self.type == .use {
  741. let fileName = "\(pdfDocument.documentURL?.deletingPathExtension().lastPathComponent ?? NSLocalizedString("Untitled", comment: ""))_Watermark"
  742. let savePanelAccessoryViewController = KMSavePanelAccessoryController()
  743. let savePanel = NSSavePanel()
  744. savePanel.nameFieldStringValue = fileName
  745. savePanel.allowedFileTypes = ["pdf"]
  746. savePanel.accessoryView = savePanelAccessoryViewController.view
  747. savePanel.beginSheetModal(for: self.window!) { [unowned self] result in
  748. if result == NSApplication.ModalResponse.OK {
  749. self.addWatermark(model: self.watermark, toPath: savePanel.url!.path) { success in
  750. if success {
  751. if savePanelAccessoryViewController.openAutomaticButton.state == .on {
  752. NSDocumentController.shared.openDocument(withContentsOf: savePanel.url!, display: true) { (document, documentWasAlreadyOpen, error) in
  753. }
  754. } else {
  755. NSWorkspace.shared.activateFileViewerSelecting([savePanel.url!])
  756. }
  757. self.cancelAction?(self)
  758. }
  759. }
  760. }
  761. }
  762. }
  763. }
  764. @IBAction func colorWellColorChanged(_ sender: NSColorWell) {
  765. self.watermark.textColor = KMWatermarkAdjectiveText.color(red: sender.color.redComponent, green: sender.color.greenComponent, blue: sender.color.blueComponent, alpha: sender.color.alphaComponent)
  766. updatePDFView()
  767. }
  768. @IBAction func radioStepperAction(_ sender: NSStepper) {
  769. self.ratioTextField.stringValue = "\(Int(sender.doubleValue * 100))%"
  770. self.watermark.scale = sender.doubleValue
  771. updatePDFView()
  772. }
  773. @IBAction func angleStepperAction(_ sender: NSStepper) {
  774. self.angleTextF.stringValue = "\(sender.doubleValue)"
  775. self.watermark.rotation = sender.doubleValue
  776. checkAngle()
  777. updatePDFView()
  778. }
  779. @IBAction func alphaSliderAction(_ sender: NSSlider) {
  780. self.watermark.opacity = sender.doubleValue
  781. self.alphaStepper.doubleValue = sender.doubleValue
  782. self.alphaTextField.stringValue = "\(Int(sender.doubleValue * 100))%"
  783. updatePDFView()
  784. }
  785. @IBAction func verticalStepperAction(_ sender: NSStepper) {
  786. self.verticalFapTextField.stringValue = "\(sender.doubleValue)"
  787. self.watermark.verticalSpace = sender.doubleValue
  788. updatePDFView()
  789. }
  790. @IBAction func tileVerticalStepperAction(_ sender: NSStepper) {
  791. self.watermark.tileVerticalSpace = sender.doubleValue
  792. self.spacingVerTextField.stringValue = "\(sender.doubleValue)"
  793. self.watermark.tileVerticalSpace = sender.doubleValue
  794. updatePDFView()
  795. }
  796. @IBAction func horizentalStepperAction(_ sender: NSStepper) {
  797. self.watermark.horizontalSpace = sender.doubleValue
  798. self.horizentalGapTextField.stringValue = "\(sender.doubleValue)"
  799. self.watermark.horizontalSpace = sender.doubleValue
  800. updatePDFView()
  801. }
  802. @IBAction func tileHorizentalStepperAction(_ sender: NSStepper) {
  803. self.watermark.tileHorizontalSpace = sender.doubleValue
  804. self.spacingHorTextField.stringValue = "\(sender.doubleValue)"
  805. self.watermark.tileHorizontalSpace = sender.doubleValue
  806. updatePDFView()
  807. }
  808. @IBAction func alphaSteperAction(_ sender: NSStepper) {
  809. self.alphaTextField.stringValue = "\(Int(sender.doubleValue * 100))%"
  810. self.watermark.opacity = sender.doubleValue
  811. self.alphaSlider.doubleValue = sender.doubleValue
  812. updatePDFView()
  813. }
  814. @IBAction func onPageButtonAction(_ sender: Any) {
  815. self.backPageButton.state = .off
  816. self.watermark.isFront = true
  817. updatePDFView()
  818. }
  819. @IBAction func backPageButtonAction(_ sender: Any) {
  820. self.OnPageButton.state = .off
  821. self.watermark.isFront = false
  822. updatePDFView()
  823. }
  824. @IBAction func onPageTileButtonAction(_ sender: Any) {
  825. self.watermark.isTilePage = !self.watermark.isTilePage
  826. if self.type != .edit && !self.fontModified && self.txtButton.state == .on {
  827. if self.watermark.isTilePage {
  828. let textSize = self.watermark.getTextFontSize() == 48 ? 18 : self.watermark.getTextFontSize()
  829. self.isTileWater.state = .on
  830. self.fontSizeCombobox.stringValue = "\(Int(textSize))"
  831. self.watermark.textFont = KMWatermarkAdjectiveText.font(name: "Helvetica", size: textSize)
  832. } else {
  833. let textSize = self.watermark.getTextFontSize() == 18 ? 48 : self.watermark.getTextFontSize()
  834. self.fontSizeCombobox.stringValue = "\(Int(textSize))"
  835. self.watermark.textFont = KMWatermarkAdjectiveText.font(name: "Helvetica", size: textSize)
  836. }
  837. }
  838. self.spacingHorTextField.isEnabled = self.watermark.isTilePage
  839. self.spacingHorStepper.isEnabled = self.watermark.isTilePage
  840. self.spacingVerTextField.isEnabled = self.watermark.isTilePage
  841. self.spacingStepper.isEnabled = self.watermark.isTilePage
  842. updatePDFView()
  843. }
  844. @IBAction func goPrevious(_ sender: Any) {
  845. if pdfView.canGoToPreviousPage() {
  846. pdfView.goToPreviousPage(sender)
  847. }
  848. let index = pdfDocument?.index(for: pdfView.currentPage())
  849. // currentPageIndexTextF.stringValue = "\(index! + 1)"
  850. }
  851. @IBAction func goNext(_ sender: Any) {
  852. if pdfView.canGoToNextPage() {
  853. pdfView.goToNextPage(sender)
  854. }
  855. let index = pdfDocument!.index(for: pdfView.currentPage())
  856. // currentPageIndexTextF.stringValue = "\(index + 1)"
  857. }
  858. @IBAction func fontSizeComboxAction(_ sender: NSComboBox) {
  859. let textSize = CGFloat(Int(fontSizeCombobox.stringValue) ?? 0)
  860. self.watermark.textFont = KMWatermarkAdjectiveText.font(name: "Helvetica", size: textSize)
  861. fontModified = true
  862. updatePDFView()
  863. }
  864. @IBAction func pageRangeComboxAction(_ sender: Any) {
  865. pageRangeComboBox.isEditable = false
  866. var pages = [Int]()
  867. switch pageRangeComboBox.indexOfSelectedItem {
  868. case 0:
  869. for i in 0..<pdfDocument!.pageCount {
  870. pages.append(Int(i))
  871. }
  872. watermark.pageRangeType = .all
  873. case 1:
  874. for i in 0..<pdfDocument!.pageCount where i % 2 == 0 {
  875. pages.append(Int(i))
  876. }
  877. watermark.pageRangeType = .odd
  878. case 2:
  879. for i in 0..<pdfDocument!.pageCount where i % 2 != 0 {
  880. pages.append(Int(i))
  881. }
  882. watermark.pageRangeType = .even
  883. default:
  884. var fileAttribute = self._fileAttri
  885. if fileAttribute == nil {
  886. fileAttribute = KMFileAttribute()
  887. fileAttribute?.filePath = pdfDocument?.documentURL?.path ?? ""
  888. self._fileAttri = fileAttribute
  889. }
  890. fileAttribute?.bAllPage = false
  891. fileAttribute?.pagesString = pageRangeComboBox.stringValue
  892. watermark.pageRangeType = .other
  893. pageRangeComboBox.isEditable = true
  894. window?.makeFirstResponder(pageRangeComboBox)
  895. let selectPages = fileAttribute?.fetchSelectPages() ?? []
  896. pages = selectPages.map { $0 - 1 }
  897. }
  898. if !pages.isEmpty {
  899. watermark.pagesString = pages.map { "\($0)" }.joined(separator: ",")
  900. } else {
  901. watermark.pagesString = ""
  902. }
  903. updatePDFView()
  904. }
  905. }
  906. extension KMWatermarkView {
  907. class func addWatermarkForOutSide(document: CPDFDocument, model: KMWatermarkModel, toPath: String, completion: @escaping (_ result: Bool) -> ()) {
  908. DispatchQueue.main.async {
  909. let wm = KMWatermarkView()
  910. wm.pdfView = KMWatermarkPDFView()
  911. wm.pdfView.document = document
  912. wm.password = document.password ?? ""
  913. wm.addWatermark(model: model, toPath: toPath, completion: completion)
  914. }
  915. }
  916. func addWatermark(model: KMWatermarkModel, toPath: String, completion: @escaping (_ result: Bool) -> ()) {
  917. DispatchQueue.global().async {
  918. let waterDocument = CPDFDocument(url: self.pdfView.document.documentURL)
  919. guard let waterDocumentT = waterDocument else { return }
  920. if self.password.isEmpty == false {
  921. waterDocumentT.unlock(withPassword: self.password)
  922. }
  923. var property: CPDFWatermark!
  924. var scale: CGFloat = model.scale
  925. if model.image != nil {
  926. property = CPDFWatermark(document: waterDocument, type: .image)
  927. property.image = model.image
  928. } else {
  929. property = CPDFWatermark(document: waterDocument, type: .text)
  930. property.text = model.text
  931. property.textColor = model.getTextColor()
  932. scale = model.getTextFontSize() / 24.0
  933. }
  934. property.scale = scale
  935. property.rotation = -model.rotation
  936. property.opacity = model.opacity
  937. property.tx = model.horizontalSpace
  938. property.ty = model.verticalSpace
  939. property.isFront = model.isFront
  940. var pageString: String = ""
  941. if (model.pageRangeType == .all) {
  942. for i in 0..<waterDocumentT.pageCount {
  943. pageString.append("\(i)")
  944. if (i != waterDocumentT.pageCount-1) {
  945. pageString.append(",")
  946. }
  947. }
  948. } else if (model.pageRangeType == .odd) {
  949. for i in 0 ..< waterDocumentT.pageCount {
  950. if (i % 2 == 0) {
  951. pageString.append("\(i)")
  952. } else {
  953. continue
  954. }
  955. if (i != waterDocumentT.pageCount-1) {
  956. pageString.append(",")
  957. }
  958. }
  959. } else if (model.pageRangeType == .even) {
  960. for i in 0 ..< waterDocumentT.pageCount {
  961. if (i % 2 == 1) {
  962. pageString.append("\(i)")
  963. } else {
  964. continue
  965. }
  966. if (i != waterDocumentT.pageCount-1) {
  967. pageString.append(",")
  968. }
  969. }
  970. } else {
  971. pageString = model.pagesString
  972. }
  973. property.pageString = pageString
  974. property.isTilePage = model.isTilePage
  975. property.horizontalSpacing = model.tileHorizontalSpace / scale
  976. property.verticalSpacing = model.tileVerticalSpace / scale
  977. if (model.verticalMode == 0) {
  978. property.verticalPosition = .top
  979. } else if (model.verticalMode == 1) {
  980. property.verticalPosition = .center
  981. } else if (model.verticalMode == 2) {
  982. property.verticalPosition = .bottom
  983. }
  984. if (model.horizontalMode == 0) {
  985. property.horizontalPosition = .left
  986. } else if (model.horizontalMode == 1) {
  987. property.horizontalPosition = .center
  988. } else if (model.horizontalMode == 2) {
  989. property.horizontalPosition = .right
  990. }
  991. model.watermark = property
  992. waterDocumentT.addWatermark(property)
  993. /// 保存到临时路径
  994. let documentPath = NSTemporaryDirectory()
  995. let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
  996. if (FileManager.default.fileExists(atPath: tempPath)) {
  997. try?FileManager.default.removeItem(atPath: tempPath)
  998. }
  999. let result = waterDocumentT.write(to: URL(fileURLWithPath: tempPath))
  1000. if (result) {
  1001. if (FileManager.default.fileExists(atPath: toPath)) {
  1002. try?FileManager.default.removeItem(atPath: toPath)
  1003. }
  1004. try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
  1005. } else {
  1006. try?FileManager.default.removeItem(atPath: tempPath)
  1007. }
  1008. DispatchQueue.main.async {
  1009. completion(result)
  1010. }
  1011. }
  1012. // static func loadAllWatermarks() {
  1013. // self.watermarkArray.removeAll()
  1014. // let watermarks: Array<CPDFWatermark> = self.preView.document.watermarks()
  1015. // for watermark in watermarks {
  1016. // let model = KMWatermarkModel()
  1017. // model.scale = watermark.scale
  1018. // model.rotation = -watermark.rotation
  1019. // model.opacity = watermark.opacity
  1020. // model.verticalSpace = watermark.tx
  1021. // model.horizontalSpace = watermark.ty
  1022. // model.pagesString = watermark.pageString
  1023. //// model.textColor = watermark.textColor
  1024. // model.isFront = watermark.isFront
  1025. // model.isTilePage = watermark.isTilePage
  1026. // model.tileVerticalSpace = watermark.verticalSpacing
  1027. // model.tileHorizontalSpace = watermark.horizontalSpacing
  1028. //
  1029. // if (watermark.type == .text) {
  1030. // model.text = watermark.text
  1031. //// model.textFont
  1032. // model.scale = watermark.scale * 24
  1033. // } else if (watermark.type == .image) {
  1034. // model.image = watermark.image
  1035. // }
  1036. //
  1037. // if (watermark.verticalPosition == .top) {
  1038. // model.verticalMode = 0
  1039. // } else if (watermark.verticalPosition == .center) {
  1040. // model.verticalMode = 1
  1041. // } else if (watermark.verticalPosition == .bottom) {
  1042. // model.verticalMode = 2
  1043. // }
  1044. //
  1045. // if (watermark.horizontalPosition == .left) {
  1046. // model.horizontalMode = 0
  1047. // } else if (watermark.horizontalPosition == .center) {
  1048. // model.horizontalMode = 1
  1049. // } else if (watermark.horizontalPosition == .right) {
  1050. // model.horizontalMode = 2
  1051. // }
  1052. //
  1053. // model.watermark = watermark
  1054. // self.watermarkArray.append(model)
  1055. // }
  1056. // }
  1057. }
  1058. func deleteWatermarks(toPath: String, completion: @escaping (_ result: Bool) -> ()) -> () {
  1059. if (self.pdfView.document.watermarks().count <= 0) {
  1060. completion(false)
  1061. }
  1062. DispatchQueue.global().async {
  1063. let array: Array<CPDFWatermark> = self.pdfView.document.watermarks()
  1064. for model in array {
  1065. self.pdfView.document.removeWatermark(model)
  1066. }
  1067. /// 保存到临时路径
  1068. let documentPath = NSTemporaryDirectory()
  1069. let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
  1070. if (FileManager.default.fileExists(atPath: tempPath)) {
  1071. try?FileManager.default.removeItem(atPath: tempPath)
  1072. }
  1073. let result = self.pdfView.document.write(to: URL(fileURLWithPath: tempPath))
  1074. if (result) {
  1075. if (FileManager.default.fileExists(atPath: toPath)) {
  1076. try?FileManager.default.removeItem(atPath: toPath)
  1077. }
  1078. try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
  1079. } else {
  1080. try?FileManager.default.removeItem(atPath: tempPath)
  1081. }
  1082. DispatchQueue.main.async {
  1083. completion(result)
  1084. }
  1085. }
  1086. }
  1087. }