KMWatermarkManager.swift 19 KB

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