KMWatermarkManager.swift 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. //
  2. // KMWatermarkManager.swift
  3. // PDF Master
  4. //
  5. // Created by tangchao on 2022/12/19.
  6. //
  7. import Cocoa
  8. enum KMWatermarkKey: String {
  9. case text = "text"
  10. case textFontSize = "textFontSize"
  11. case textFontName = "textFontName"
  12. case imagePath = "imagePath"
  13. case rotate = "rotate"
  14. case opacity = "opacity"
  15. case scale = "scale"
  16. case verticalMode = "verticalMode"
  17. case verticalSpace = "verticalSpace"
  18. case horizontalMode = "horizontalMode"
  19. case horizontalSpace = "horizontalSpace"
  20. case isFront = "isFront"
  21. case red = "red"
  22. case green = "green"
  23. case blue = "blue"
  24. case createDate = "createDate"
  25. case pageRangeType = "pageRangeType"
  26. case pageRangeString = "pageRangeString"
  27. case tileVerticalSpace = "tileVerticalSpace"
  28. case tileHorizontalSpace = "tileHorizontalSpace"
  29. case isTile = "isTile"
  30. case lastAddData = "lastAddData"
  31. case id = "id"
  32. }
  33. class KMWatermarkManager: NSObject {
  34. let watermarkFolderPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier!).stringByAppendingPathComponent("watermark")
  35. let watermarkPlistPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier!).stringByAppendingPathComponent("watermark").stringByAppendingPathComponent("watermark.plist")
  36. static let defaultManager = KMWatermarkManager()
  37. var watermarks: Array<KMWatermarkModel> = []
  38. override init() {
  39. super.init()
  40. if (FileManager.default.fileExists(atPath: watermarkPlistPath!)) {
  41. let dataDict = NSDictionary(contentsOfFile: watermarkPlistPath!)
  42. var deleteKeys: Array<String> = []
  43. for keyIndex in 0 ..< (dataDict?.allKeys.count)! {
  44. let key: String = dataDict?.allKeys[keyIndex] as! String
  45. let watermarkDict: NSDictionary = dataDict?.object(forKey: key) as! NSDictionary
  46. let model = parseDictionary(dict: watermarkDict)
  47. /// 赋值tag
  48. model.tag = key
  49. let isFile: Bool = (watermarkDict.object(forKey: KMWatermarkKey.imagePath.rawValue) != nil)
  50. if (isFile) {
  51. if (model.image == nil) {
  52. deleteKeys.append(key)
  53. } else {
  54. self.watermarks.append(model)
  55. }
  56. } else {
  57. self.watermarks.append(model)
  58. }
  59. }
  60. /// 根据id进行排序(升序)
  61. self.watermarks.sort(){$0.watermarkID > $1.watermarkID}
  62. if (deleteKeys.count > 0) {
  63. var newDict: NSMutableDictionary = NSMutableDictionary(dictionary: dataDict!)
  64. for key in deleteKeys {
  65. newDict.removeObject(forKey: key)
  66. }
  67. newDict.write(toFile: watermarkPlistPath!, atomically: true)
  68. }
  69. }
  70. }
  71. func addWatermark(watermark: KMWatermarkModel) -> Bool {
  72. if (!FileManager.default.fileExists(atPath: watermarkFolderPath!)) {
  73. let create = try?FileManager.default.createDirectory(atPath: watermarkFolderPath!, withIntermediateDirectories: false)
  74. if (create == nil) {
  75. return false
  76. }
  77. }
  78. if (!FileManager.default.fileExists(atPath: watermarkPlistPath!)) {
  79. let create = try?FileManager.default.createFile(atPath: watermarkPlistPath!, contents: nil)
  80. if (create == nil) {
  81. return false
  82. }
  83. }
  84. let dict = NSDictionary(contentsOfFile: watermarkPlistPath!)
  85. var newDict:NSMutableDictionary!
  86. if (dict != nil) {
  87. newDict = NSMutableDictionary(dictionary: dict!)
  88. } else {
  89. newDict = NSMutableDictionary()
  90. }
  91. let watermarkDict = self.parseModel(model: watermark)
  92. if (watermarkDict.isEmpty) {
  93. let alert = NSAlert()
  94. alert.alertStyle = .critical
  95. alert.messageText = NSLocalizedString("文件\(watermark.imagePath.lastPathComponent)已损坏", comment: "")
  96. alert.runModal()
  97. return false
  98. }
  99. let tag = tagString()
  100. newDict.addEntries(from: [tag : watermarkDict])
  101. watermark.tag = tag
  102. let result = newDict.write(toFile: watermarkPlistPath!, atomically: true)
  103. if (result) {
  104. if (self.watermarks.count < 1) {
  105. self.watermarks.append(watermark)
  106. } else {
  107. self.watermarks.insert(watermark, at: 0)
  108. }
  109. }
  110. return result
  111. }
  112. func updateWatermark(watermark: KMWatermarkModel) -> Bool {
  113. if (!FileManager.default.fileExists(atPath: watermarkFolderPath!)) {
  114. let create = try?FileManager.default.createDirectory(atPath: watermarkFolderPath!, withIntermediateDirectories: false)
  115. if (create == nil) {
  116. return false
  117. }
  118. }
  119. if (!FileManager.default.fileExists(atPath: watermarkPlistPath!)) {
  120. let create = try?FileManager.default.createFile(atPath: watermarkPlistPath!, contents: nil)
  121. if (create == nil) {
  122. return false
  123. }
  124. }
  125. var flagModel: KMWatermarkModel!
  126. for model in self.watermarks {
  127. if (model.tag == watermark.tag) {
  128. flagModel = model
  129. break
  130. }
  131. }
  132. if (flagModel == nil) {
  133. return false
  134. }
  135. let dict = NSDictionary(contentsOfFile: watermarkPlistPath!)
  136. var newDict:NSMutableDictionary!
  137. if (dict != nil) {
  138. newDict = NSMutableDictionary(dictionary: dict!)
  139. } else {
  140. newDict = NSMutableDictionary()
  141. }
  142. let watermarkDict = self.parseModel(model: watermark)
  143. if (watermarkDict.isEmpty) {
  144. let alert = NSAlert()
  145. alert.alertStyle = .critical
  146. alert.messageText = NSLocalizedString("文件\(watermark.imagePath.lastPathComponent)已损坏", comment: "")
  147. alert.runModal()
  148. return false
  149. }
  150. newDict.setObject(watermarkDict, forKey: flagModel.tag! as NSCopying)
  151. let result = newDict.write(toFile: watermarkPlistPath!, atomically: true)
  152. if (result) {
  153. let index = self.watermarks.index(of: flagModel)
  154. self.watermarks[index!] = watermark
  155. }
  156. return result
  157. }
  158. func removeWatermark(watermark: KMWatermarkModel) -> Bool {
  159. if (watermark == nil) {
  160. return false
  161. }
  162. if (watermark.tag == nil) {
  163. return false
  164. }
  165. if (!FileManager.default.fileExists(atPath: watermarkPlistPath!)) {
  166. return false
  167. }
  168. let key: String = watermark.tag
  169. let dictionary = NSDictionary(contentsOfFile: watermarkPlistPath!)
  170. var newDictionary: NSMutableDictionary!
  171. if (dictionary != nil) {
  172. newDictionary = NSMutableDictionary(dictionary: dictionary!)
  173. } else {
  174. newDictionary = NSMutableDictionary()
  175. }
  176. newDictionary.removeObject(forKey: key)
  177. let result = newDictionary.write(toFile: watermarkPlistPath!, atomically: true)
  178. if (result) {
  179. if (watermark.text == nil || watermark.text.isEmpty) {
  180. let filePath: String = watermark.imagePath
  181. try?FileManager.default.removeItem(atPath: filePath)
  182. }
  183. if (self.watermarks.contains(watermark)) {
  184. self.watermarks.removeObject(watermark)
  185. }
  186. }
  187. return result
  188. }
  189. func removeAllWatermark() -> Bool {
  190. if (!FileManager.default.fileExists(atPath: watermarkPlistPath!)) {
  191. return false
  192. }
  193. let dictionary = NSDictionary(contentsOfFile: watermarkPlistPath!)
  194. var newDictionary: NSMutableDictionary!
  195. if (dictionary != nil) {
  196. newDictionary = NSMutableDictionary(dictionary: dictionary!)
  197. } else {
  198. newDictionary = NSMutableDictionary()
  199. }
  200. newDictionary.removeAllObjects()
  201. let result = newDictionary.write(toFile: watermarkPlistPath!, atomically: true)
  202. if (result) {
  203. self.watermarks.removeAll()
  204. }
  205. return result
  206. }
  207. func removeAllTextWatermarks() -> Bool {
  208. if (!FileManager.default.fileExists(atPath: watermarkPlistPath!)) {
  209. return false
  210. }
  211. let dictionary = NSDictionary(contentsOfFile: watermarkPlistPath!)
  212. var newDictionary: NSMutableDictionary!
  213. if (dictionary != nil) {
  214. newDictionary = NSMutableDictionary(dictionary: dictionary!)
  215. } else {
  216. newDictionary = NSMutableDictionary()
  217. }
  218. let count = self.watermarks.count-1
  219. var deleteArray: Array<KMWatermarkModel> = []
  220. for i in 0 ... count {
  221. let model = self.watermarks[i]
  222. if (model.text != nil && !model.text.isEmpty) {
  223. newDictionary.removeObject(forKey: model.tag as Any)
  224. deleteArray.append(model)
  225. }
  226. }
  227. let result = newDictionary.write(toFile: watermarkPlistPath!, atomically: true)
  228. if (result) {
  229. for model in deleteArray {
  230. self.watermarks.removeObject(model)
  231. }
  232. }
  233. return result
  234. }
  235. func removeAllFileWatermarks() -> Bool {
  236. if (!FileManager.default.fileExists(atPath: watermarkPlistPath!)) {
  237. return false
  238. }
  239. let dictionary = NSDictionary(contentsOfFile: watermarkPlistPath!)
  240. var newDictionary: NSMutableDictionary!
  241. if (dictionary != nil) {
  242. newDictionary = NSMutableDictionary(dictionary: dictionary!)
  243. } else {
  244. newDictionary = NSMutableDictionary()
  245. }
  246. let count = self.watermarks.count-1
  247. var deleteArray: Array<KMWatermarkModel> = []
  248. for i in 0 ... count {
  249. let model = self.watermarks[i]
  250. if (model.image != nil) {
  251. newDictionary.removeObject(forKey: model.tag as Any)
  252. deleteArray.append(model)
  253. }
  254. }
  255. let result = newDictionary.write(toFile: watermarkPlistPath!, atomically: true)
  256. if (result) {
  257. for model in deleteArray {
  258. self.watermarks.removeObject(model)
  259. }
  260. }
  261. return result
  262. }
  263. private func parseModel(model: KMWatermarkModel) -> Dictionary<String, Any> {
  264. let tag = tagString()
  265. let dateFormatter = DateFormatter()
  266. dateFormatter.dateFormat = "yy-MM-dd HH:mm:ss"
  267. let timeString = dateFormatter.string(from: Date())
  268. model.creatTemplateDate = timeString
  269. var dict: [String : Any] = [:]
  270. if (!model.text.isEmpty) {
  271. dict[KMWatermarkKey.text.rawValue] = model.text
  272. dict[KMWatermarkKey.textFontSize.rawValue] = model.getTextFontSize()
  273. dict[KMWatermarkKey.textFontName.rawValue] = model.getTextFontName()
  274. } else {
  275. if (!FileManager.default.fileExists(atPath: watermarkFolderPath!)) {
  276. try?FileManager.default.createDirectory(atPath: watermarkFolderPath!, withIntermediateDirectories: false)
  277. }
  278. let path = watermarkFolderPath?.stringByAppendingPathComponent("\(tag).png")
  279. let image = model.image
  280. let data = image?.tiffRepresentation
  281. let imageRep = NSBitmapImageRep(data: data!)
  282. imageRep?.size = image!.size
  283. var imageData: Data!
  284. let pathExtension = model.imagePath.components(separatedBy: ".").last
  285. if (pathExtension?.lowercased() == "png") {
  286. imageData = imageRep?.representation(using: NSBitmapImageRep.FileType.png, properties: [:])
  287. } else {
  288. imageData = imageRep?.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [:])
  289. }
  290. do {
  291. try imageData.write(to: URL(fileURLWithPath: path!))
  292. dict[KMWatermarkKey.imagePath.rawValue] = path?.lastPathComponent
  293. }
  294. catch {
  295. KMPrint("Failed to write to disk.")
  296. return [:]
  297. }
  298. }
  299. var red: CGFloat = 0.0
  300. var green: CGFloat = 0.0
  301. var blue: CGFloat = 0.0
  302. model.getTextColor().usingColorSpaceName(NSColorSpaceName.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: nil)
  303. dict[KMWatermarkKey.isFront.rawValue] = model.isFront
  304. dict[KMWatermarkKey.scale.rawValue] = model.scale
  305. dict[KMWatermarkKey.opacity.rawValue] = model.opacity
  306. dict[KMWatermarkKey.rotate.rawValue] = model.rotation
  307. dict[KMWatermarkKey.verticalMode.rawValue] = model.verticalMode
  308. dict[KMWatermarkKey.verticalSpace.rawValue] = model.verticalSpace
  309. dict[KMWatermarkKey.horizontalMode.rawValue] = model.horizontalMode
  310. dict[KMWatermarkKey.horizontalSpace.rawValue] = model.horizontalSpace
  311. dict[KMWatermarkKey.red.rawValue] = red
  312. dict[KMWatermarkKey.green.rawValue] = green
  313. dict[KMWatermarkKey.blue.rawValue] = blue
  314. dict[KMWatermarkKey.isTile.rawValue] = model.isTilePage
  315. dict[KMWatermarkKey.tileVerticalSpace.rawValue] = model.tileVerticalSpace
  316. dict[KMWatermarkKey.tileHorizontalSpace.rawValue] = model.tileHorizontalSpace
  317. dict[KMWatermarkKey.pageRangeType.rawValue] = model.pageRangeType
  318. dict[KMWatermarkKey.pageRangeString.rawValue] = model.pagesString
  319. dict[KMWatermarkKey.createDate.rawValue] = model.creatTemplateDate
  320. dict[KMWatermarkKey.id.rawValue] = model.watermarkID
  321. return dict
  322. }
  323. private func parseDictionary(dict: NSDictionary) -> KMWatermarkModel {
  324. let model = KMWatermarkModel()
  325. let isText: Bool = (dict.object(forKey: KMWatermarkKey.text.rawValue) != nil)
  326. let isFile: Bool = (dict.object(forKey: KMWatermarkKey.imagePath.rawValue) != nil)
  327. if (isText) {
  328. model.text = (dict.object(forKey: KMWatermarkKey.text.rawValue) as! String)
  329. let fontSize: CGFloat = dict.object(forKey: KMWatermarkKey.textFontSize.rawValue) as! CGFloat
  330. let fontName: String = dict.object(forKey: KMWatermarkKey.textFontName.rawValue) as! String
  331. model.textFont = .font(name: fontName, size: fontSize)
  332. } else if (isFile) {
  333. let path = watermarkFolderPath?.stringByAppendingPathComponent(dict.object(forKey: KMWatermarkKey.imagePath.rawValue) as! String)
  334. if (FileManager.default.fileExists(atPath: path!)) {
  335. model.image = NSImage(contentsOfFile: path!)
  336. model.imagePath = path
  337. } else {
  338. model.image = nil
  339. }
  340. }
  341. model.scale = (dict.object(forKey: KMWatermarkKey.scale.rawValue) as! CGFloat)
  342. model.rotation = dict.object(forKey: KMWatermarkKey.rotate.rawValue) as! CGFloat
  343. model.opacity = (dict.object(forKey: KMWatermarkKey.opacity.rawValue) as! CGFloat)
  344. model.verticalMode = (dict.object(forKey: KMWatermarkKey.verticalMode.rawValue) as! Int)
  345. model.verticalSpace = dict.object(forKey: KMWatermarkKey.verticalSpace.rawValue) as! CGFloat
  346. model.horizontalMode = (dict.object(forKey: KMWatermarkKey.horizontalMode.rawValue) as! Int)
  347. model.horizontalSpace = dict.object(forKey: KMWatermarkKey.horizontalSpace.rawValue) as! CGFloat
  348. let red: CGFloat = dict.object(forKey: KMWatermarkKey.red.rawValue) as! CGFloat
  349. let green: CGFloat = dict.object(forKey: KMWatermarkKey.green.rawValue) as! CGFloat
  350. let blue: CGFloat = dict.object(forKey: KMWatermarkKey.blue.rawValue) as! CGFloat
  351. model.textColor = .color(red: red, green: green, blue: blue, alpha: 1.0)
  352. model.isFront = (dict.object(forKey: KMWatermarkKey.isFront.rawValue) != nil)
  353. model.pageRangeType = (dict.object(forKey: KMWatermarkKey.pageRangeType.rawValue) as! Int)
  354. model.pagesString = (dict.object(forKey: KMWatermarkKey.pageRangeString.rawValue) as! String)
  355. model.isTilePage = (dict.object(forKey: KMWatermarkKey.isTile.rawValue) as! Bool)
  356. model.tileHorizontalSpace = (dict.object(forKey: KMWatermarkKey.tileHorizontalSpace.rawValue) as! CGFloat)
  357. model.tileVerticalSpace = (dict.object(forKey: KMWatermarkKey.tileVerticalSpace.rawValue) as! CGFloat)
  358. model.watermarkID = (dict.object(forKey: KMWatermarkKey.id.rawValue) as! String)
  359. model.creatTemplateDate = (dict.object(forKey: KMWatermarkKey.createDate.rawValue) as! String)
  360. return model
  361. }
  362. func fetchAvailableName() -> String {
  363. var availableIndex: Int = 0
  364. let watermark = "Watermark"
  365. for model in self.watermarks {
  366. let watermarkID = model.watermarkID
  367. if (((watermarkID?.hasPrefix(watermark))!)) {
  368. let indexString: String = (watermarkID?.components(separatedBy: watermark).last)!
  369. let index: Int = Int(indexString)!
  370. if (index >= availableIndex) {
  371. availableIndex = index + 1
  372. }
  373. }
  374. }
  375. return "\(watermark)\(availableIndex)"
  376. }
  377. /**
  378. Private Methods
  379. */
  380. private func tagString() -> String {
  381. var result: String = ""
  382. let dateFormatter = DateFormatter()
  383. dateFormatter.dateFormat = "yyMMddHHmmss"
  384. result.append(dateFormatter.string(from: Date()))
  385. result = result.appendingFormat("%04d", arc4random()%10000)
  386. return result
  387. }
  388. }