KMWatermarkAdjectiveTools.swift 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  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. let array = document.watermarks() ?? []
  164. for model in array {
  165. document.removeWatermark(model)
  166. }
  167. }
  168. /// 保存到临时路径
  169. let documentPath = NSTemporaryDirectory()
  170. let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
  171. if (FileManager.default.fileExists(atPath: tempPath)) {
  172. try?FileManager.default.removeItem(atPath: tempPath)
  173. }
  174. let result = document.write(to: URL(fileURLWithPath: tempPath))
  175. if (result) {
  176. if (FileManager.default.fileExists(atPath: toPath)) {
  177. try?FileManager.default.removeItem(atPath: toPath)
  178. }
  179. try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
  180. } else {
  181. try?FileManager.default.removeItem(atPath: tempPath)
  182. }
  183. DispatchQueue.main.async {
  184. completion(result)
  185. }
  186. }
  187. }
  188. private class func applyBates(_ model: KMHeaderFooterObject, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
  189. DispatchQueue.global().async {
  190. let document: CPDFDocument = pdfView.document
  191. var property = document.bates()
  192. var fontSize = 0.0
  193. var fontName: String = ""
  194. switch model.textFont {
  195. case .font(name: let name, size: let size):
  196. fontName = name
  197. fontSize = size
  198. break
  199. default:
  200. break
  201. }
  202. let font = NSFont.boldSystemFont(ofSize:fontSize)
  203. let style = NSMutableParagraphStyle()
  204. style.alignment = .center
  205. style.lineBreakMode = .byCharWrapping
  206. 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
  207. property?.margin = NSEdgeInsetsMake(max(CGFloat(model.topMargin)-size.height, 0), CGFloat(model.leftMargin), max(CGFloat(model.bottomMargin)-size.height, 0), CGFloat(model.rightMargin))
  208. let strings = [model.topLeftString, model.topCenterString, model.topRightString, model.bottomLeftString, model.bottomCenterString, model.bottomRightString]
  209. var count: Int = 0
  210. var color: NSColor!
  211. switch model.textColor {
  212. case .color(red: let red, green: let green, blue: let blue, alpha: let alpha):
  213. color = NSColor(red: red, green: green, blue: blue, alpha: alpha)
  214. default:
  215. break
  216. }
  217. if (color == nil) {
  218. color = NSColor.black
  219. }
  220. for text in strings {
  221. property?.setText(text, at: UInt(count))
  222. property?.setTextColor(color, at: UInt(count))
  223. property?.setFontSize(fontSize, at: UInt(count))
  224. property?.setFontName(fontName, at: UInt(count))
  225. count += 1
  226. }
  227. let pagesString = KMWatermarkAdjectiveTools.findPagesString(model)
  228. if (pagesString.isEmpty) {
  229. property?.pageString = "0-\(document.pageCount-1)"
  230. } else {
  231. property?.pageString = pagesString
  232. }
  233. property?.update()
  234. /// 保存到临时路径
  235. let documentPath = NSTemporaryDirectory()
  236. let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
  237. if (FileManager.default.fileExists(atPath: tempPath)) {
  238. try?FileManager.default.removeItem(atPath: tempPath)
  239. }
  240. let result = document.write(to: URL(fileURLWithPath: tempPath))
  241. if (result) {
  242. if (FileManager.default.fileExists(atPath: toPath)) {
  243. try?FileManager.default.removeItem(atPath: toPath)
  244. }
  245. try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
  246. } else {
  247. try?FileManager.default.removeItem(atPath: tempPath)
  248. }
  249. DispatchQueue.main.async {
  250. completion(result)
  251. }
  252. }
  253. }
  254. private class func applyHeaderFooter(_ model: KMHeaderFooterObject, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
  255. DispatchQueue.global().async {
  256. let document: CPDFDocument = pdfView.document
  257. var property = document.headerFooter()
  258. var fontSize = 0.0
  259. var fontName: String = ""
  260. switch model.textFont {
  261. case .font(name: let name, size: let size):
  262. fontSize = size
  263. fontName = name
  264. break
  265. default:
  266. break
  267. }
  268. let font = NSFont.boldSystemFont(ofSize:fontSize)
  269. let style = NSMutableParagraphStyle()
  270. style.alignment = .center
  271. style.lineBreakMode = .byCharWrapping
  272. 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
  273. property?.margin = NSEdgeInsetsMake(max(CGFloat(model.topMargin)-size.height, 0), CGFloat(model.leftMargin), max(CGFloat(model.bottomMargin)-size.height, 0), CGFloat(model.rightMargin))
  274. let strings = KMWatermarkAdjectiveTools.parseModel(model: model, pdfView.document.pageCount)
  275. var count: Int = 0
  276. var color: NSColor!
  277. switch model.textColor {
  278. case .color(red: let red, green: let green, blue: let blue, alpha: let alpha):
  279. color = NSColor(red: red, green: green, blue: blue, alpha: alpha)
  280. default:
  281. break
  282. }
  283. if (color == nil) {
  284. color = NSColor.black
  285. }
  286. for text in strings {
  287. property?.setText(text, at: UInt(count))
  288. property?.setTextColor(color, at: UInt(count))
  289. property?.setFontSize(fontSize, at: UInt(count))
  290. property?.setFontName(fontName, at: UInt(count))
  291. count += 1
  292. }
  293. let pagesString = KMWatermarkAdjectiveTools.findPagesString(model)
  294. if (pagesString.isEmpty) {
  295. property?.pageString = "0-\(document.pageCount-1)"
  296. } else {
  297. property?.pageString = pagesString
  298. }
  299. property?.update()
  300. /// 保存到临时路径
  301. let documentPath = NSTemporaryDirectory()
  302. let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
  303. if (FileManager.default.fileExists(atPath: tempPath)) {
  304. try?FileManager.default.removeItem(atPath: tempPath)
  305. }
  306. let result = document.write(to: URL(fileURLWithPath: tempPath))
  307. if (result) {
  308. if (FileManager.default.fileExists(atPath: toPath)) {
  309. try?FileManager.default.removeItem(atPath: toPath)
  310. }
  311. try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
  312. } else {
  313. try?FileManager.default.removeItem(atPath: tempPath)
  314. }
  315. DispatchQueue.main.async {
  316. completion(result)
  317. }
  318. }
  319. }
  320. private class func applyBackground(_ model: KMBackgroundModel, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
  321. DispatchQueue.global().async {
  322. let document: CPDFDocument = pdfView.document
  323. var property = document.background()
  324. property!.scale = model.scale
  325. property!.rotation = CGFloat(-model.rotation)
  326. property!.opacity = model.opacity
  327. property?.xOffset = model.horizontalSpace
  328. property?.yOffset = model.verticalSpace
  329. property?.horizontalAlignment = UInt(model.horizontalMode)
  330. property?.verticalAlignment = UInt(model.verticalMode)
  331. if (model.type == .color) {
  332. property?.color = model.color
  333. property?.type = .color
  334. } else if (model.type == .file) {
  335. property?.setImage(NSImage(contentsOfFile: model.imagePath))
  336. // property?.setImage(model.image)
  337. property?.type = .image
  338. }
  339. property?.pageString = "0-\(document.pageCount-1)"
  340. property?.update()
  341. /// 保存到临时路径
  342. let documentPath = NSTemporaryDirectory()
  343. let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
  344. if (FileManager.default.fileExists(atPath: tempPath)) {
  345. try?FileManager.default.removeItem(atPath: tempPath)
  346. }
  347. let result = document.write(to: URL(fileURLWithPath: tempPath))
  348. if (result) {
  349. if (FileManager.default.fileExists(atPath: toPath)) {
  350. try?FileManager.default.removeItem(atPath: toPath)
  351. }
  352. try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
  353. } else {
  354. try?FileManager.default.removeItem(atPath: tempPath)
  355. }
  356. DispatchQueue.main.async {
  357. completion(result)
  358. }
  359. }
  360. }
  361. private class func applyWatermark(_ model: KMWatermarkModel, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
  362. DispatchQueue.global().async {
  363. var property: CPDFWatermark!
  364. var scale: CGFloat = model.scale
  365. if (!model.text.isEmpty) {
  366. property = CPDFWatermark(document: pdfView.document, type: .text)
  367. property.text = model.text
  368. property.textColor = model.getTextColor()
  369. scale = model.getTextFontSize() / 24.0
  370. } else {
  371. property = CPDFWatermark(document: pdfView.document, type: .image)
  372. property.image = model.image
  373. }
  374. property.scale = scale
  375. property.rotation = -model.rotation
  376. property.opacity = model.opacity
  377. property.tx = model.horizontalSpace
  378. property.ty = model.verticalSpace
  379. property.isFront = model.isFront
  380. var pageString: String = ""
  381. if (model.pageRangeType == .all) {
  382. for i in 0 ..< pdfView.document.pageCount {
  383. pageString.append("\(i)")
  384. if (i != pdfView.document.pageCount-1) {
  385. pageString.append(",")
  386. }
  387. }
  388. } else if (model.pageRangeType == .odd) {
  389. for i in 0 ..< pdfView.document.pageCount {
  390. if (i % 2 == 0) {
  391. pageString.append("\(i)")
  392. } else {
  393. continue
  394. }
  395. if (i != pdfView.document.pageCount-1) {
  396. pageString.append(",")
  397. }
  398. }
  399. } else if (model.pageRangeType == .even) {
  400. for i in 0 ..< pdfView.document.pageCount {
  401. if (i % 2 == 1) {
  402. pageString.append("\(i)")
  403. } else {
  404. continue
  405. }
  406. if (i != pdfView.document.pageCount-1) {
  407. pageString.append(",")
  408. }
  409. }
  410. } else {
  411. pageString = model.pagesString
  412. }
  413. property.pageString = pageString
  414. property.isTilePage = model.isTilePage
  415. property.horizontalSpacing = model.tileHorizontalSpace / scale
  416. property.verticalSpacing = model.tileVerticalSpace / scale
  417. if (model.verticalMode == 0) {
  418. property.verticalPosition = .top
  419. } else if (model.verticalMode == 1) {
  420. property.verticalPosition = .center
  421. } else if (model.verticalMode == 2) {
  422. property.verticalPosition = .bottom
  423. }
  424. if (model.horizontalMode == 0) {
  425. property.horizontalPosition = .left
  426. } else if (model.horizontalMode == 1) {
  427. property.horizontalPosition = .center
  428. } else if (model.horizontalMode == 2) {
  429. property.horizontalPosition = .right
  430. }
  431. model.watermark = property
  432. pdfView.document.addWatermark(property)
  433. /// 保存到临时路径
  434. let documentPath = NSTemporaryDirectory()
  435. let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
  436. if (FileManager.default.fileExists(atPath: tempPath)) {
  437. try?FileManager.default.removeItem(atPath: tempPath)
  438. }
  439. let result = pdfView.document.write(to: URL(fileURLWithPath: tempPath))
  440. if (result) {
  441. if (FileManager.default.fileExists(atPath: toPath)) {
  442. try?FileManager.default.removeItem(atPath: toPath)
  443. }
  444. try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
  445. } else {
  446. try?FileManager.default.removeItem(atPath: tempPath)
  447. }
  448. DispatchQueue.main.async {
  449. completion(result)
  450. }
  451. }
  452. }
  453. // MARK: Add
  454. class func add(_ model: AnyObject, _ pdfView: CPDFView, completion: @escaping (_ result: Bool) -> ()) {
  455. if (model.isKind(of: KMHeaderFooterObject.self)) {
  456. // KMWatermarkAdjectiveTools.applyBates(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
  457. } else if (model.isKind(of: KMHeaderFooterObject.self)) {
  458. // KMWatermarkAdjectiveTools.applyHeaderFooter(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
  459. } else if (model.isKind(of: KMBackgroundModel.self)) {
  460. // KMWatermarkAdjectiveTools.applyBackground(model as! KMBackgroundModel, pdfView, toPath, completion: completion)
  461. } else if (model.isKind(of: KMWatermarkModel.self)) {
  462. KMWatermarkAdjectiveTools.addWatermark(model as! KMWatermarkModel, pdfView, completion: completion)
  463. }
  464. }
  465. private class func addWatermark(_ model: KMWatermarkModel, _ pdfView: CPDFView, completion: @escaping (_ result: Bool) -> ()) {
  466. DispatchQueue.global().async {
  467. var property: CPDFWatermark!
  468. var scale: CGFloat = model.scale
  469. if (!model.text.isEmpty) {
  470. property = CPDFWatermark(document: pdfView.document, type: .text)
  471. property.text = model.text
  472. property.textColor = model.getTextColor()
  473. scale = model.getTextFontSize() / 24.0
  474. } else {
  475. property = CPDFWatermark(document: pdfView.document, type: .image)
  476. property.image = model.image
  477. }
  478. property.scale = scale
  479. property.rotation = -model.rotation
  480. property.opacity = model.opacity
  481. property.tx = model.horizontalSpace
  482. property.ty = model.verticalSpace
  483. property.isFront = model.isFront
  484. var pageString: String = ""
  485. if (model.pageRangeType == .all) {
  486. for i in 0 ..< pdfView.document.pageCount {
  487. pageString.append("\(i)")
  488. if (i != pdfView.document.pageCount-1) {
  489. pageString.append(",")
  490. }
  491. }
  492. } else if (model.pageRangeType == .odd) {
  493. for i in 0 ..< pdfView.document.pageCount {
  494. if (i % 2 == 0) {
  495. pageString.append("\(i)")
  496. } else {
  497. continue
  498. }
  499. if (i != pdfView.document.pageCount-1) {
  500. pageString.append(",")
  501. }
  502. }
  503. } else if (model.pageRangeType == .even) {
  504. for i in 0 ..< pdfView.document.pageCount {
  505. if (i % 2 == 1) {
  506. pageString.append("\(i)")
  507. } else {
  508. continue
  509. }
  510. if (i != pdfView.document.pageCount-1) {
  511. pageString.append(",")
  512. }
  513. }
  514. } else {
  515. pageString = model.pagesString
  516. }
  517. property.pageString = pageString
  518. property.isTilePage = model.isTilePage
  519. property.horizontalSpacing = model.tileHorizontalSpace / scale
  520. property.verticalSpacing = model.tileVerticalSpace / scale
  521. if (model.verticalMode == 0) {
  522. property.verticalPosition = .top
  523. } else if (model.verticalMode == 1) {
  524. property.verticalPosition = .center
  525. } else if (model.verticalMode == 2) {
  526. property.verticalPosition = .bottom
  527. }
  528. if (model.horizontalMode == 0) {
  529. property.horizontalPosition = .left
  530. } else if (model.horizontalMode == 1) {
  531. property.horizontalPosition = .center
  532. } else if (model.horizontalMode == 2) {
  533. property.horizontalPosition = .right
  534. }
  535. model.watermark = property
  536. let result = pdfView.document.addWatermark(property)
  537. DispatchQueue.main.async {
  538. completion(result)
  539. }
  540. }
  541. }
  542. // MARK: Update
  543. class func update(_ model: AnyObject, _ pdfView: CPDFView, completion: @escaping (_ result: Bool) -> ()) {
  544. if (model.isKind(of: KMHeaderFooterObject.self)) {
  545. // KMWatermarkAdjectiveTools.applyBates(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
  546. } else if (model.isKind(of: KMHeaderFooterObject.self)) {
  547. // KMWatermarkAdjectiveTools.applyHeaderFooter(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
  548. } else if (model.isKind(of: KMBackgroundModel.self)) {
  549. // KMWatermarkAdjectiveTools.applyBackground(model as! KMBackgroundModel, pdfView, toPath, completion: completion)
  550. } else if (model.isKind(of: KMWatermarkModel.self)) {
  551. KMWatermarkAdjectiveTools.updateWatermark(model as! KMWatermarkModel, pdfView, completion: completion)
  552. }
  553. }
  554. private class func updateWatermark(_ model: KMWatermarkModel, _ pdfView: CPDFView, completion: @escaping (_ result: Bool) -> ()) {
  555. DispatchQueue.global().async {
  556. var property: CPDFWatermark!
  557. var scale: CGFloat = model.scale
  558. if (!model.text.isEmpty) {
  559. property = CPDFWatermark(document: pdfView.document, type: .text)
  560. property.text = model.text
  561. property.textColor = model.getTextColor()
  562. scale = model.getTextFontSize() / 24.0
  563. } else {
  564. property = CPDFWatermark(document: pdfView.document, type: .image)
  565. property.image = model.image
  566. }
  567. property.scale = scale
  568. property.rotation = -model.rotation
  569. property.opacity = model.opacity
  570. property.tx = model.horizontalSpace
  571. property.ty = model.verticalSpace
  572. property.isFront = model.isFront
  573. var pageString: String = ""
  574. if (model.pageRangeType == .all) {
  575. for i in 0 ..< pdfView.document.pageCount {
  576. pageString.append("\(i)")
  577. if (i != pdfView.document.pageCount-1) {
  578. pageString.append(",")
  579. }
  580. }
  581. } else if (model.pageRangeType == .odd) {
  582. for i in 0 ..< pdfView.document.pageCount {
  583. if (i % 2 == 0) {
  584. pageString.append("\(i)")
  585. } else {
  586. continue
  587. }
  588. if (i != pdfView.document.pageCount-1) {
  589. pageString.append(",")
  590. }
  591. }
  592. } else if (model.pageRangeType == .even) {
  593. for i in 0 ..< pdfView.document.pageCount {
  594. if (i % 2 == 1) {
  595. pageString.append("\(i)")
  596. } else {
  597. continue
  598. }
  599. if (i != pdfView.document.pageCount-1) {
  600. pageString.append(",")
  601. }
  602. }
  603. } else {
  604. pageString = model.pagesString
  605. }
  606. property.pageString = pageString
  607. property.isTilePage = model.isTilePage
  608. property.horizontalSpacing = model.tileHorizontalSpace / scale
  609. property.verticalSpacing = model.tileVerticalSpace / scale
  610. if (model.verticalMode == 0) {
  611. property.verticalPosition = .top
  612. } else if (model.verticalMode == 1) {
  613. property.verticalPosition = .center
  614. } else if (model.verticalMode == 2) {
  615. property.verticalPosition = .bottom
  616. }
  617. if (model.horizontalMode == 0) {
  618. property.horizontalPosition = .left
  619. } else if (model.horizontalMode == 1) {
  620. property.horizontalPosition = .center
  621. } else if (model.horizontalMode == 2) {
  622. property.horizontalPosition = .right
  623. }
  624. model.watermark = property
  625. let watermarks = pdfView.document.watermarks()
  626. if (watermarks != nil) {
  627. for i in 0 ..< watermarks!.count {
  628. let watermark = watermarks![i]
  629. pdfView.document.removeWatermark(watermark)
  630. }
  631. }
  632. let result = pdfView.document.addWatermark(property)
  633. DispatchQueue.main.async {
  634. completion(result)
  635. }
  636. }
  637. }
  638. private class func parseModel(model: KMHeaderFooterObject, _ pageCount: UInt) -> [String] {
  639. var topLeftString: String = ""
  640. if (!model.topLeftString.isEmpty) {
  641. var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.topLeftString, startPage: model.startString, pageCount: "\(pageCount)")
  642. string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
  643. topLeftString = string
  644. }
  645. var topCenterString: String = ""
  646. if (!model.topCenterString.isEmpty) {
  647. var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.topCenterString, startPage: model.startString, pageCount: "\(pageCount)")
  648. string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
  649. topCenterString = string
  650. }
  651. var topRightString: String = ""
  652. if (!model.topRightString.isEmpty) {
  653. var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.topRightString, startPage: model.startString, pageCount: "\(pageCount)")
  654. string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
  655. topRightString = string
  656. }
  657. var bottomLeftString: String = ""
  658. if (!model.bottomLeftString.isEmpty) {
  659. var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.bottomLeftString, startPage: model.startString, pageCount: "\(pageCount)")
  660. string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
  661. bottomLeftString = string
  662. }
  663. var bottomCenterString: String = ""
  664. if (!model.bottomCenterString.isEmpty) {
  665. var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.bottomCenterString, startPage: model.startString, pageCount: "\(pageCount)")
  666. string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
  667. bottomCenterString = string
  668. }
  669. var bottomRightString: String = ""
  670. if (!model.bottomRightString.isEmpty) {
  671. var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.bottomRightString, startPage: model.startString, pageCount: "\(pageCount)")
  672. string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
  673. bottomRightString = string
  674. }
  675. return [topLeftString, topCenterString, topRightString, bottomLeftString, bottomCenterString, bottomRightString]
  676. }
  677. class func findPagesString(_ model: KMWatermarkAdjectiveBaseModel) -> String{
  678. if (model.pageRangeType == .all) { /// 全部页面
  679. return "0-\(model.pageCount-1)"
  680. } else if (model.pageRangeType == .odd) { /// 奇数页面
  681. var string: String = ""
  682. for i in 0 ..< model.pageCount {
  683. if (i % 2 == 1) {
  684. continue
  685. }
  686. string.append("\(i)")
  687. if (i != model.pageCount-1) {
  688. string.append(",")
  689. }
  690. }
  691. return string
  692. } else if (model.pageRangeType == .even) { /// 偶数页面
  693. var string: String = ""
  694. for i in 0 ..< model.pageCount {
  695. if (i % 2 == 0) {
  696. continue
  697. }
  698. string.append("\(i)")
  699. if (i != model.pageCount-1) {
  700. string.append(",")
  701. }
  702. }
  703. return string
  704. } else { /// 自定义
  705. return model.pageRangeString
  706. }
  707. }
  708. }