KMWatermarkAdjectiveTools.swift 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. //
  2. // KMWatermarkAdjectiveTools.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by tangchao on 2022/12/27.
  6. //
  7. import Cocoa
  8. enum KMWatermarkAdjectiveType: Int {
  9. case watermark = 1
  10. case background = 2
  11. case headerfooter = 3
  12. case bates = 4
  13. }
  14. @objc class KMWatermarkAdjectiveTools: NSObject {
  15. class func fetchAvailableFonts(_ size: CGFloat) -> [NSAttributedString] {
  16. let fonts = NSFontManager.shared.availableFontFamilies
  17. var result: Array<NSAttributedString> = []
  18. for fontName in fonts {
  19. let font = NSFont(name: fontName, size: size)
  20. let attribute = [NSAttributedString.Key.font : font]
  21. let string = NSAttributedString(string: fontName, attributes: attribute as [NSAttributedString.Key : Any])
  22. result.append(string)
  23. }
  24. return result
  25. }
  26. class func fontNameToAttribute(_ name: String, _ size: CGFloat) -> NSAttributedString? {
  27. let names = NSFontManager.shared.availableFontFamilies
  28. if (!names.contains(name)) {
  29. return nil
  30. }
  31. let font = NSFont(name: name, size: size)
  32. if (font == nil) {
  33. return nil
  34. }
  35. let attribute = [NSAttributedString.Key.font : font]
  36. return NSAttributedString(string: name, attributes: attribute as [NSAttributedString.Key : Any])
  37. }
  38. class func parseColor(color: NSColor) -> (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
  39. var red: CGFloat = 0.0
  40. var green: CGFloat = 0.0
  41. var blue: CGFloat = 0.0
  42. var alpha: CGFloat = 0.0
  43. color.usingColorSpaceName(NSColorSpaceName.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
  44. return (red, green, blue, alpha)
  45. }
  46. @objc class func getDateFormats() -> [String] {
  47. return ["m/d", "m/d/yy", "m/d/yyyy",
  48. "mm/dd/yy", "mm/dd/yyyy",
  49. "d/m/yy", "d/m/yyyy",
  50. "dd/mm/yy", "dd/mm/yyyy",
  51. "mm/yy", "mm/yyyy",
  52. "m.d.yy", "m.d.yyyy",
  53. "mm.dd.yy", "mm.dd.yyyy", "mm.yy", "mm.yyyy",
  54. "d.m.yy", "d.m.yyyy",
  55. "dd.mm.yy", "dd.mm.yyyy",
  56. "yy-mm-dd",
  57. "yyyy-mm-dd"]
  58. }
  59. class func getPageFormats() -> [String] {
  60. return ["1",
  61. "1 of n",
  62. "1/n",
  63. "Page 1",
  64. "Page 1 of n"]
  65. }
  66. class func parsePageFormat(formatString: String, startPage: String, pageCount: String) -> String {
  67. var result = formatString
  68. for pageFormat in self.getPageFormats() {
  69. let string = "<<\(pageFormat)>>"
  70. if (result.contains(string)) {
  71. var tempString = ""
  72. if (string == "<<1>>") {
  73. tempString.append("<<\(startPage)>>")
  74. } else if (string == "<<1 of n>>") {
  75. tempString.append("<<\(startPage)>>")
  76. tempString.append(" of \(pageCount)")
  77. } else if (string == "<<1/n>>") {
  78. tempString.append("<<\(startPage)>>")
  79. tempString.append("/\(pageCount)")
  80. } else if (string == "<<Page 1>>") {
  81. tempString.append("Page \(startPage)")
  82. } else if (string == "<<Page 1 of n>>") {
  83. tempString.append("Page \(startPage)")
  84. tempString.append("of \(pageCount)")
  85. }
  86. result = result.replacingOccurrences(of: string, with: tempString)
  87. }
  88. }
  89. return result
  90. }
  91. class func parseDateFormat(formatString: String) -> String {
  92. var result: String = formatString
  93. for dateFormat in self.getDateFormats() {
  94. if (result.contains(dateFormat)) {
  95. var formatString: String = dateFormat.replacingOccurrences(of: "m", with: "M")
  96. var replace = "<<\(dateFormat)>>"
  97. let date = Date()
  98. let dateFormatter = DateFormatter()
  99. dateFormatter.dateFormat = formatString
  100. var dateString = dateFormatter.string(from: date)
  101. result = result.replacingOccurrences(of: replace, with: dateString)
  102. }
  103. }
  104. return result
  105. }
  106. class func KMWatermarkAdjectiveType(from toolBarType: KMToolbarType) -> KMWatermarkAdjectiveType {
  107. if (toolBarType == .bates) {
  108. return .bates
  109. } else if (toolBarType == .headerAndFooter) {
  110. return .headerfooter
  111. } else if (toolBarType == .background) {
  112. return .background
  113. } else if (toolBarType == .watermark) {
  114. return .watermark
  115. }
  116. return .watermark
  117. }
  118. class func KMToolBarTypeToRightSubViewType(_ type: KMToolbarType) -> RightSubViewType {
  119. if (type == .bates) {
  120. return .Bates
  121. } else if (type == .headerAndFooter) {
  122. return .Headerfooter
  123. } else if (type == .background) {
  124. return .Background
  125. } else if (type == .watermark) {
  126. return .Watermark
  127. }
  128. return .None
  129. }
  130. // MARK: Apply
  131. class func apply(_ model: AnyObject, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
  132. if (model.isKind(of: KMHeaderFooterObject.self)) {
  133. KMWatermarkAdjectiveTools.applyBates(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
  134. } else if (model.isKind(of: KMHeaderFooterObject.self)) {
  135. KMWatermarkAdjectiveTools.applyHeaderFooter(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
  136. } else if (model.isKind(of: KMBackgroundModel.self)) {
  137. KMWatermarkAdjectiveTools.applyBackground(model as! KMBackgroundModel, pdfView, toPath, completion: completion)
  138. } else if (model.isKind(of: KMWatermarkModel.self)) {
  139. KMWatermarkAdjectiveTools.applyWatermark(model as! KMWatermarkModel, pdfView, toPath, completion: completion)
  140. }
  141. }
  142. class func delete(_ type: KMWatermarkAdjectiveType, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
  143. if (pdfView.document.allowsPrinting == false || pdfView.document.allowsCopying == false) {
  144. let alert = NSAlert()
  145. alert.alertStyle = .critical
  146. alert.messageText = NSLocalizedString("This PDF document's user permissions does not allow modifying, content copying and printing.", comment: "")
  147. alert.runModal()
  148. completion(false)
  149. return
  150. }
  151. DispatchQueue.global().async {
  152. let document: CPDFDocument = CPDFDocument(url: pdfView.document.documentURL)
  153. if (type == .bates) {
  154. let property = document.bates()
  155. property?.clear()
  156. } else if (type == .headerfooter) {
  157. let property = document.headerFooter()
  158. property?.clear()
  159. } else if (type == .background) {
  160. let property = document.background()
  161. property?.clear()
  162. } else if (type == .watermark) {
  163. guard let tempArr = document.watermarks() else {
  164. return
  165. }
  166. let array: Array<CPDFWatermark> = document.watermarks()
  167. for model in array {
  168. document.removeWatermark(model)
  169. }
  170. }
  171. /// 保存到临时路径
  172. let documentPath = NSTemporaryDirectory()
  173. let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
  174. if (FileManager.default.fileExists(atPath: tempPath)) {
  175. try?FileManager.default.removeItem(atPath: tempPath)
  176. }
  177. let result = document.write(to: URL(fileURLWithPath: tempPath))
  178. if (result) {
  179. if (FileManager.default.fileExists(atPath: toPath)) {
  180. try?FileManager.default.removeItem(atPath: toPath)
  181. }
  182. try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
  183. } else {
  184. try?FileManager.default.removeItem(atPath: tempPath)
  185. }
  186. DispatchQueue.main.async {
  187. completion(result)
  188. }
  189. }
  190. }
  191. private class func applyBates(_ model: KMHeaderFooterObject, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
  192. DispatchQueue.global().async {
  193. let document: CPDFDocument = pdfView.document
  194. var property = document.bates()
  195. var fontSize = 0.0
  196. var fontName: String = ""
  197. switch model.textFont {
  198. case .font(name: let name, size: let size):
  199. fontName = name
  200. fontSize = size
  201. break
  202. default:
  203. break
  204. }
  205. let font = NSFont.boldSystemFont(ofSize:fontSize)
  206. let style = NSMutableParagraphStyle()
  207. style.alignment = .center
  208. style.lineBreakMode = .byCharWrapping
  209. let size: NSSize = "text".boundingRect(with: NSSize(width: 1000, height: 1000), options: NSString.DrawingOptions(rawValue: 3), attributes: [NSAttributedString.Key.font : font, NSAttributedString.Key.paragraphStyle : style]).size
  210. property?.margin = NSEdgeInsetsMake(max(CGFloat(model.topMargin)-size.height, 0), CGFloat(model.leftMargin), max(CGFloat(model.bottomMargin)-size.height, 0), CGFloat(model.rightMargin))
  211. let strings = [model.topLeftString, model.topCenterString, model.topRightString, model.bottomLeftString, model.bottomCenterString, model.bottomRightString]
  212. var count: Int = 0
  213. var color: NSColor!
  214. switch model.textColor {
  215. case .color(red: let red, green: let green, blue: let blue, alpha: let alpha):
  216. color = NSColor(red: red, green: green, blue: blue, alpha: alpha)
  217. default:
  218. break
  219. }
  220. if (color == nil) {
  221. color = NSColor.black
  222. }
  223. for text in strings {
  224. property?.setText(text, at: UInt(count))
  225. property?.setTextColor(color, at: UInt(count))
  226. property?.setFontSize(fontSize, at: UInt(count))
  227. property?.setFontName(fontName, at: UInt(count))
  228. count += 1
  229. }
  230. let pagesString = KMWatermarkAdjectiveTools.findPagesString(model)
  231. if (pagesString.isEmpty) {
  232. property?.pageString = "0-\(document.pageCount-1)"
  233. } else {
  234. property?.pageString = pagesString
  235. }
  236. property?.update()
  237. /// 保存到临时路径
  238. let documentPath = NSTemporaryDirectory()
  239. let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
  240. if (FileManager.default.fileExists(atPath: tempPath)) {
  241. try?FileManager.default.removeItem(atPath: tempPath)
  242. }
  243. let result = document.write(to: URL(fileURLWithPath: tempPath))
  244. if (result) {
  245. if (FileManager.default.fileExists(atPath: toPath)) {
  246. try?FileManager.default.removeItem(atPath: toPath)
  247. }
  248. try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
  249. } else {
  250. try?FileManager.default.removeItem(atPath: tempPath)
  251. }
  252. DispatchQueue.main.async {
  253. completion(result)
  254. }
  255. }
  256. }
  257. private class func applyHeaderFooter(_ model: KMHeaderFooterObject, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
  258. DispatchQueue.global().async {
  259. let document: CPDFDocument = pdfView.document
  260. var property = document.headerFooter()
  261. var fontSize = 0.0
  262. var fontName: String = ""
  263. switch model.textFont {
  264. case .font(name: let name, size: let size):
  265. fontSize = size
  266. fontName = name
  267. break
  268. default:
  269. break
  270. }
  271. let font = NSFont.boldSystemFont(ofSize:fontSize)
  272. let style = NSMutableParagraphStyle()
  273. style.alignment = .center
  274. style.lineBreakMode = .byCharWrapping
  275. let size: NSSize = "text".boundingRect(with: NSSize(width: 1000, height: 1000), options: NSString.DrawingOptions(rawValue: 3), attributes: [NSAttributedString.Key.font : font, NSAttributedString.Key.paragraphStyle : style]).size
  276. property?.margin = NSEdgeInsetsMake(max(CGFloat(model.topMargin)-size.height, 0), CGFloat(model.leftMargin), max(CGFloat(model.bottomMargin)-size.height, 0), CGFloat(model.rightMargin))
  277. let strings = KMWatermarkAdjectiveTools.parseModel(model: model, pdfView.document.pageCount)
  278. var count: Int = 0
  279. var color: NSColor!
  280. switch model.textColor {
  281. case .color(red: let red, green: let green, blue: let blue, alpha: let alpha):
  282. color = NSColor(red: red, green: green, blue: blue, alpha: alpha)
  283. default:
  284. break
  285. }
  286. if (color == nil) {
  287. color = NSColor.black
  288. }
  289. for text in strings {
  290. property?.setText(text, at: UInt(count))
  291. property?.setTextColor(color, at: UInt(count))
  292. property?.setFontSize(fontSize, at: UInt(count))
  293. property?.setFontName(fontName, at: UInt(count))
  294. count += 1
  295. }
  296. let pagesString = KMWatermarkAdjectiveTools.findPagesString(model)
  297. if (pagesString.isEmpty) {
  298. property?.pageString = "0-\(document.pageCount-1)"
  299. } else {
  300. property?.pageString = pagesString
  301. }
  302. property?.update()
  303. /// 保存到临时路径
  304. let documentPath = NSTemporaryDirectory()
  305. let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
  306. if (FileManager.default.fileExists(atPath: tempPath)) {
  307. try?FileManager.default.removeItem(atPath: tempPath)
  308. }
  309. let result = document.write(to: URL(fileURLWithPath: tempPath))
  310. if (result) {
  311. if (FileManager.default.fileExists(atPath: toPath)) {
  312. try?FileManager.default.removeItem(atPath: toPath)
  313. }
  314. try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
  315. } else {
  316. try?FileManager.default.removeItem(atPath: tempPath)
  317. }
  318. DispatchQueue.main.async {
  319. completion(result)
  320. }
  321. }
  322. }
  323. private class func applyBackground(_ model: KMBackgroundModel, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
  324. DispatchQueue.global().async {
  325. let document: CPDFDocument = pdfView.document
  326. var property = document.background()
  327. property!.scale = model.scale
  328. property!.rotation = CGFloat(-model.rotation)
  329. property!.opacity = model.opacity
  330. property?.xOffset = model.horizontalSpace
  331. property?.yOffset = model.verticalSpace
  332. property?.horizontalAlignment = UInt(model.horizontalMode)
  333. property?.verticalAlignment = UInt(model.verticalMode)
  334. if (model.type == .color) {
  335. property?.color = model.color
  336. property?.type = .color
  337. } else if (model.type == .file) {
  338. property?.setImage(NSImage(contentsOfFile: model.imagePath))
  339. // property?.setImage(model.image)
  340. property?.type = .image
  341. }
  342. property?.pageString = "0-\(document.pageCount-1)"
  343. property?.update()
  344. /// 保存到临时路径
  345. let documentPath = NSTemporaryDirectory()
  346. let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
  347. if (FileManager.default.fileExists(atPath: tempPath)) {
  348. try?FileManager.default.removeItem(atPath: tempPath)
  349. }
  350. let result = document.write(to: URL(fileURLWithPath: tempPath))
  351. if (result) {
  352. if (FileManager.default.fileExists(atPath: toPath)) {
  353. try?FileManager.default.removeItem(atPath: toPath)
  354. }
  355. try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
  356. } else {
  357. try?FileManager.default.removeItem(atPath: tempPath)
  358. }
  359. DispatchQueue.main.async {
  360. completion(result)
  361. }
  362. }
  363. }
  364. private class func applyWatermark(_ model: KMWatermarkModel, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
  365. DispatchQueue.global().async {
  366. var property: CPDFWatermark!
  367. var scale: CGFloat = model.scale
  368. if (!model.text.isEmpty) {
  369. property = CPDFWatermark(document: pdfView.document, type: .text)
  370. property.text = model.text
  371. property.textColor = model.getTextColor()
  372. scale = model.getTextFontSize() / 24.0
  373. } else {
  374. property = CPDFWatermark(document: pdfView.document, type: .image)
  375. property.image = model.image
  376. }
  377. property.scale = scale
  378. property.rotation = -model.rotation
  379. property.opacity = model.opacity
  380. property.tx = model.horizontalSpace
  381. property.ty = model.verticalSpace
  382. property.isFront = model.isFront
  383. var pageString: String = ""
  384. if (model.pageRangeType == .all) {
  385. for i in 0 ..< pdfView.document.pageCount {
  386. pageString.append("\(i)")
  387. if (i != pdfView.document.pageCount-1) {
  388. pageString.append(",")
  389. }
  390. }
  391. } else if (model.pageRangeType == .odd) {
  392. for i in 0 ..< pdfView.document.pageCount {
  393. if (i % 2 == 0) {
  394. pageString.append("\(i)")
  395. } else {
  396. continue
  397. }
  398. if (i != pdfView.document.pageCount-1) {
  399. pageString.append(",")
  400. }
  401. }
  402. } else if (model.pageRangeType == .even) {
  403. for i in 0 ..< pdfView.document.pageCount {
  404. if (i % 2 == 1) {
  405. pageString.append("\(i)")
  406. } else {
  407. continue
  408. }
  409. if (i != pdfView.document.pageCount-1) {
  410. pageString.append(",")
  411. }
  412. }
  413. } else {
  414. pageString = model.pagesString
  415. }
  416. property.pageString = pageString
  417. property.isTilePage = model.isTilePage
  418. property.horizontalSpacing = model.tileHorizontalSpace / scale
  419. property.verticalSpacing = model.tileVerticalSpace / scale
  420. if (model.verticalMode == 0) {
  421. property.verticalPosition = .top
  422. } else if (model.verticalMode == 1) {
  423. property.verticalPosition = .center
  424. } else if (model.verticalMode == 2) {
  425. property.verticalPosition = .bottom
  426. }
  427. if (model.horizontalMode == 0) {
  428. property.horizontalPosition = .left
  429. } else if (model.horizontalMode == 1) {
  430. property.horizontalPosition = .center
  431. } else if (model.horizontalMode == 2) {
  432. property.horizontalPosition = .right
  433. }
  434. model.watermark = property
  435. pdfView.document.addWatermark(property)
  436. /// 保存到临时路径
  437. let documentPath = NSTemporaryDirectory()
  438. let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
  439. if (FileManager.default.fileExists(atPath: tempPath)) {
  440. try?FileManager.default.removeItem(atPath: tempPath)
  441. }
  442. let result = pdfView.document.write(to: URL(fileURLWithPath: tempPath))
  443. if (result) {
  444. if (FileManager.default.fileExists(atPath: toPath)) {
  445. try?FileManager.default.removeItem(atPath: toPath)
  446. }
  447. try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
  448. } else {
  449. try?FileManager.default.removeItem(atPath: tempPath)
  450. }
  451. DispatchQueue.main.async {
  452. completion(result)
  453. }
  454. }
  455. }
  456. // MARK: Add
  457. class func add(_ model: AnyObject, _ pdfView: CPDFView, completion: @escaping (_ result: Bool) -> ()) {
  458. if (model.isKind(of: KMHeaderFooterObject.self)) {
  459. // KMWatermarkAdjectiveTools.applyBates(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
  460. } else if (model.isKind(of: KMHeaderFooterObject.self)) {
  461. // KMWatermarkAdjectiveTools.applyHeaderFooter(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
  462. } else if (model.isKind(of: KMBackgroundModel.self)) {
  463. // KMWatermarkAdjectiveTools.applyBackground(model as! KMBackgroundModel, pdfView, toPath, completion: completion)
  464. } else if (model.isKind(of: KMWatermarkModel.self)) {
  465. KMWatermarkAdjectiveTools.addWatermark(model as! KMWatermarkModel, pdfView, completion: completion)
  466. }
  467. }
  468. private class func addWatermark(_ model: KMWatermarkModel, _ pdfView: CPDFView, completion: @escaping (_ result: Bool) -> ()) {
  469. DispatchQueue.global().async {
  470. var property: CPDFWatermark!
  471. var scale: CGFloat = model.scale
  472. if (!model.text.isEmpty) {
  473. property = CPDFWatermark(document: pdfView.document, type: .text)
  474. property.text = model.text
  475. property.textColor = model.getTextColor()
  476. scale = model.getTextFontSize() / 24.0
  477. } else {
  478. property = CPDFWatermark(document: pdfView.document, type: .image)
  479. property.image = model.image
  480. }
  481. property.scale = scale
  482. property.rotation = -model.rotation
  483. property.opacity = model.opacity
  484. property.tx = model.horizontalSpace
  485. property.ty = model.verticalSpace
  486. property.isFront = model.isFront
  487. var pageString: String = ""
  488. if (model.pageRangeType == .all) {
  489. for i in 0 ..< pdfView.document.pageCount {
  490. pageString.append("\(i)")
  491. if (i != pdfView.document.pageCount-1) {
  492. pageString.append(",")
  493. }
  494. }
  495. } else if (model.pageRangeType == .odd) {
  496. for i in 0 ..< pdfView.document.pageCount {
  497. if (i % 2 == 0) {
  498. pageString.append("\(i)")
  499. } else {
  500. continue
  501. }
  502. if (i != pdfView.document.pageCount-1) {
  503. pageString.append(",")
  504. }
  505. }
  506. } else if (model.pageRangeType == .even) {
  507. for i in 0 ..< pdfView.document.pageCount {
  508. if (i % 2 == 1) {
  509. pageString.append("\(i)")
  510. } else {
  511. continue
  512. }
  513. if (i != pdfView.document.pageCount-1) {
  514. pageString.append(",")
  515. }
  516. }
  517. } else {
  518. pageString = model.pagesString
  519. }
  520. property.pageString = pageString
  521. property.isTilePage = model.isTilePage
  522. property.horizontalSpacing = model.tileHorizontalSpace / scale
  523. property.verticalSpacing = model.tileVerticalSpace / scale
  524. if (model.verticalMode == 0) {
  525. property.verticalPosition = .top
  526. } else if (model.verticalMode == 1) {
  527. property.verticalPosition = .center
  528. } else if (model.verticalMode == 2) {
  529. property.verticalPosition = .bottom
  530. }
  531. if (model.horizontalMode == 0) {
  532. property.horizontalPosition = .left
  533. } else if (model.horizontalMode == 1) {
  534. property.horizontalPosition = .center
  535. } else if (model.horizontalMode == 2) {
  536. property.horizontalPosition = .right
  537. }
  538. model.watermark = property
  539. let result = pdfView.document.addWatermark(property)
  540. DispatchQueue.main.async {
  541. completion(result)
  542. }
  543. }
  544. }
  545. // MARK: Update
  546. class func update(_ model: AnyObject, _ pdfView: CPDFView, completion: @escaping (_ result: Bool) -> ()) {
  547. if (model.isKind(of: KMHeaderFooterObject.self)) {
  548. // KMWatermarkAdjectiveTools.applyBates(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
  549. } else if (model.isKind(of: KMHeaderFooterObject.self)) {
  550. // KMWatermarkAdjectiveTools.applyHeaderFooter(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
  551. } else if (model.isKind(of: KMBackgroundModel.self)) {
  552. // KMWatermarkAdjectiveTools.applyBackground(model as! KMBackgroundModel, pdfView, toPath, completion: completion)
  553. } else if (model.isKind(of: KMWatermarkModel.self)) {
  554. KMWatermarkAdjectiveTools.updateWatermark(model as! KMWatermarkModel, pdfView, completion: completion)
  555. }
  556. }
  557. private class func updateWatermark(_ model: KMWatermarkModel, _ pdfView: CPDFView, completion: @escaping (_ result: Bool) -> ()) {
  558. DispatchQueue.global().async {
  559. var property: CPDFWatermark!
  560. var scale: CGFloat = model.scale
  561. if (!model.text.isEmpty) {
  562. property = CPDFWatermark(document: pdfView.document, type: .text)
  563. property.text = model.text
  564. property.textColor = model.getTextColor()
  565. scale = model.getTextFontSize() / 24.0
  566. } else {
  567. property = CPDFWatermark(document: pdfView.document, type: .image)
  568. property.image = model.image
  569. }
  570. property.scale = scale
  571. property.rotation = -model.rotation
  572. property.opacity = model.opacity
  573. property.tx = model.horizontalSpace
  574. property.ty = model.verticalSpace
  575. property.isFront = model.isFront
  576. var pageString: String = ""
  577. if (model.pageRangeType == .all) {
  578. for i in 0 ..< pdfView.document.pageCount {
  579. pageString.append("\(i)")
  580. if (i != pdfView.document.pageCount-1) {
  581. pageString.append(",")
  582. }
  583. }
  584. } else if (model.pageRangeType == .odd) {
  585. for i in 0 ..< pdfView.document.pageCount {
  586. if (i % 2 == 0) {
  587. pageString.append("\(i)")
  588. } else {
  589. continue
  590. }
  591. if (i != pdfView.document.pageCount-1) {
  592. pageString.append(",")
  593. }
  594. }
  595. } else if (model.pageRangeType == .even) {
  596. for i in 0 ..< pdfView.document.pageCount {
  597. if (i % 2 == 1) {
  598. pageString.append("\(i)")
  599. } else {
  600. continue
  601. }
  602. if (i != pdfView.document.pageCount-1) {
  603. pageString.append(",")
  604. }
  605. }
  606. } else {
  607. pageString = model.pagesString
  608. }
  609. property.pageString = pageString
  610. property.isTilePage = model.isTilePage
  611. property.horizontalSpacing = model.tileHorizontalSpace / scale
  612. property.verticalSpacing = model.tileVerticalSpace / scale
  613. if (model.verticalMode == 0) {
  614. property.verticalPosition = .top
  615. } else if (model.verticalMode == 1) {
  616. property.verticalPosition = .center
  617. } else if (model.verticalMode == 2) {
  618. property.verticalPosition = .bottom
  619. }
  620. if (model.horizontalMode == 0) {
  621. property.horizontalPosition = .left
  622. } else if (model.horizontalMode == 1) {
  623. property.horizontalPosition = .center
  624. } else if (model.horizontalMode == 2) {
  625. property.horizontalPosition = .right
  626. }
  627. model.watermark = property
  628. let watermarks = pdfView.document.watermarks()
  629. if (watermarks != nil) {
  630. for i in 0 ..< watermarks!.count {
  631. let watermark = watermarks![i]
  632. pdfView.document.removeWatermark(watermark)
  633. }
  634. }
  635. let result = pdfView.document.addWatermark(property)
  636. DispatchQueue.main.async {
  637. completion(result)
  638. }
  639. }
  640. }
  641. private class func parseModel(model: KMHeaderFooterObject, _ pageCount: UInt) -> [String] {
  642. var topLeftString: String = ""
  643. if (!model.topLeftString.isEmpty) {
  644. var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.topLeftString, startPage: model.startString, pageCount: "\(pageCount)")
  645. string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
  646. topLeftString = string
  647. }
  648. var topCenterString: String = ""
  649. if (!model.topCenterString.isEmpty) {
  650. var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.topCenterString, startPage: model.startString, pageCount: "\(pageCount)")
  651. string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
  652. topCenterString = string
  653. }
  654. var topRightString: String = ""
  655. if (!model.topRightString.isEmpty) {
  656. var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.topRightString, startPage: model.startString, pageCount: "\(pageCount)")
  657. string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
  658. topRightString = string
  659. }
  660. var bottomLeftString: String = ""
  661. if (!model.bottomLeftString.isEmpty) {
  662. var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.bottomLeftString, startPage: model.startString, pageCount: "\(pageCount)")
  663. string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
  664. bottomLeftString = string
  665. }
  666. var bottomCenterString: String = ""
  667. if (!model.bottomCenterString.isEmpty) {
  668. var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.bottomCenterString, startPage: model.startString, pageCount: "\(pageCount)")
  669. string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
  670. bottomCenterString = string
  671. }
  672. var bottomRightString: String = ""
  673. if (!model.bottomRightString.isEmpty) {
  674. var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.bottomRightString, startPage: model.startString, pageCount: "\(pageCount)")
  675. string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
  676. bottomRightString = string
  677. }
  678. return [topLeftString, topCenterString, topRightString, bottomLeftString, bottomCenterString, bottomRightString]
  679. }
  680. class func findPagesString(_ model: KMWatermarkAdjectiveBaseModel) -> String{
  681. if (model.pageRangeType == .all) { /// 全部页面
  682. return "0-\(model.pageCount-1)"
  683. } else if (model.pageRangeType == .odd) { /// 奇数页面
  684. var string: String = ""
  685. for i in 0 ..< model.pageCount {
  686. if (i % 2 == 1) {
  687. continue
  688. }
  689. string.append("\(i)")
  690. if (i != model.pageCount-1) {
  691. string.append(",")
  692. }
  693. }
  694. return string
  695. } else if (model.pageRangeType == .even) { /// 偶数页面
  696. var string: String = ""
  697. for i in 0 ..< model.pageCount {
  698. if (i % 2 == 0) {
  699. continue
  700. }
  701. string.append("\(i)")
  702. if (i != model.pageCount-1) {
  703. string.append(",")
  704. }
  705. }
  706. return string
  707. } else { /// 自定义
  708. return model.pageRangeString
  709. }
  710. }
  711. }