KMWatermarkManager.swift 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  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 watermarkType = "watermarkTypeKey"
  10. case text = "WatermarTextKey"
  11. case textFontSize = "WatermarkOfTextFontSizeKey"
  12. case textfontStyle = "WatermarkOfTextFontStyleKey"
  13. case textFontName = "textFontName"
  14. case textColor = "WatermarkTextColorKey"
  15. case red = "WatermarkOfRedKey"
  16. case green = "WatermarkOfGreenKey"
  17. case blue = "WatermarkOfBlueKey"
  18. case imagePath = "WatermarkOfImagePathKey"
  19. case rotate = "WatermarkOfRotationKey"
  20. case opacity = "WatermarkOfOpacityKey"
  21. case isScale = "WatermarkOfIsScaleKey"
  22. case scale = "WatermarkOfScaleKey"
  23. case verticalMode = "WatermarkOfVerticalModeKey"
  24. case verticalSpace = "WatermarkOfVerticalSpaceKey"
  25. case horizontalMode = "WatermarkOfHorizontalModeKey"
  26. case horizontalSpace = "WatermarkOfHorizontalSpaceKey"
  27. case isFront = "WatermarkOfIsFrontKey"
  28. case createDate = "WatermarkOfCreatTemplateDateKey"
  29. case pageRangeType = "WatermarkOfPageRangeTypeKey"
  30. case pageRangeString = "WatermarkOfPageStringKey"
  31. case tileVerticalSpace = "WatermarkTileVerticalSpaceKey"
  32. case tileHorizontalSpace = "WatermarkTileHorizontalSpaceKey"
  33. case isTile = "WatermarkOfIsTileKey"
  34. case lastAddData = "kAddLastWatermarkDataKey1"
  35. case id = "kWatermarkIDKey"
  36. case tag = "kWatermarkTagKey"
  37. case watermarkName = "watermarkNameKey"
  38. }
  39. class KMWatermarkManager: NSObject {
  40. let watermarkFolderPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier!).stringByAppendingPathComponent("watermark")
  41. let watermarkPlistPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier!).stringByAppendingPathComponent("watermark").stringByAppendingPathComponent("watermark.plist")
  42. let watermarkImageFolder = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier!).stringByAppendingPathComponent("watermark").stringByAppendingPathComponent("image")
  43. static let defaultManager = KMWatermarkManager()
  44. var watermarks: Array<KMWatermarkModel> = []
  45. var defaultWatermarkData = KMWatermarkModel.defaultWDData()
  46. override init() {
  47. super.init()
  48. #if DEBUG
  49. print("watermarkPlistPath=\(watermarkPlistPath ?? "")")
  50. #endif
  51. if (!FileManager.default.fileExists(atPath: watermarkFolderPath!)) {
  52. try?FileManager.default.createDirectory(atPath: watermarkFolderPath!, withIntermediateDirectories: true, attributes: nil)
  53. }
  54. if (!FileManager.default.fileExists(atPath: watermarkImageFolder!)) {
  55. let create: ()? = try?FileManager.default.createDirectory(atPath: watermarkImageFolder!, withIntermediateDirectories: false)
  56. }
  57. if (FileManager.default.fileExists(atPath: watermarkPlistPath!)) {
  58. let dataDict = NSDictionary(contentsOfFile: watermarkPlistPath!)
  59. for keyIndex in 0 ..< (dataDict?.allKeys.count ?? 0) {
  60. let key: String = dataDict?.allKeys[keyIndex] as! String
  61. let watermarkDict: NSDictionary = dataDict?.object(forKey: key) as! NSDictionary
  62. let model = parseDictionary(dict: watermarkDict)
  63. watermarks.append(model)
  64. }
  65. watermarks.sort(){$0.tag > $1.tag}
  66. }
  67. }
  68. //MARK: - 增删改查
  69. func addWatermark(watermark: KMWatermarkModel) -> Bool {
  70. if (!FileManager.default.fileExists(atPath: watermarkFolderPath!)) {
  71. let create: ()? = try?FileManager.default.createDirectory(atPath: watermarkFolderPath!, withIntermediateDirectories: true, attributes: nil)
  72. if (create == nil) {
  73. return false
  74. }
  75. }
  76. if (!FileManager.default.fileExists(atPath: watermarkPlistPath!)) {
  77. FileManager.default.createFile(atPath: watermarkPlistPath!, contents: nil)
  78. }
  79. let dict = NSDictionary(contentsOfFile: watermarkPlistPath!)
  80. var newDict:NSMutableDictionary!
  81. if (dict != nil) {
  82. newDict = NSMutableDictionary(dictionary: dict!)
  83. } else {
  84. newDict = NSMutableDictionary()
  85. }
  86. let watermarkDict = self.parseWaterMark(model: watermark)
  87. if (watermarkDict.isEmpty) {
  88. return false
  89. }
  90. let key: String = watermark.tag
  91. if newDict.object(forKey: key) != nil {
  92. newDict.setObject(watermarkDict, forKey: key as NSCopying)
  93. } else {
  94. newDict.addEntries(from: [key : watermarkDict])
  95. }
  96. let result = newDict.write(toFile: watermarkPlistPath!, atomically: true)
  97. if (result) {
  98. if (self.watermarks.count < 1) {
  99. self.watermarks.append(watermark)
  100. } else {
  101. self.watermarks.insert(watermark, at: 0)
  102. }
  103. watermark.updatePreviewImage()
  104. }
  105. return result
  106. }
  107. func updateWatermark(watermark: KMWatermarkModel) -> Bool {
  108. if (!FileManager.default.fileExists(atPath: watermarkFolderPath!)) {
  109. let create: ()? = try?FileManager.default.createDirectory(atPath: watermarkFolderPath!, withIntermediateDirectories: false)
  110. if (create == nil) {
  111. return false
  112. }
  113. }
  114. if (!FileManager.default.fileExists(atPath: watermarkPlistPath!)) {
  115. FileManager.default.createFile(atPath: watermarkPlistPath!, contents: nil)
  116. }
  117. var flagModel: KMWatermarkModel!
  118. for model in self.watermarks {
  119. if (model.tag == watermark.tag) {
  120. flagModel = model
  121. break
  122. }
  123. }
  124. if (flagModel == nil) {
  125. return false
  126. }
  127. let dict = NSDictionary(contentsOfFile: watermarkPlistPath!)
  128. var newDict:NSMutableDictionary!
  129. if (dict != nil) {
  130. newDict = NSMutableDictionary(dictionary: dict!)
  131. } else {
  132. newDict = NSMutableDictionary()
  133. }
  134. let watermarkDict = self.parseWaterMark(model: watermark)
  135. if (watermarkDict.isEmpty) {
  136. return false
  137. }
  138. newDict.setObject(watermarkDict, forKey: flagModel.tag as NSCopying)
  139. let result = newDict.write(toFile: watermarkPlistPath!, atomically: true)
  140. if (result) {
  141. if let index = self.watermarks.firstIndex(of: flagModel) {
  142. self.watermarks[index] = watermark
  143. }
  144. watermark.updatePreviewImage()
  145. }
  146. return result
  147. }
  148. func removeWatermark(watermark: KMWatermarkModel) -> Bool {
  149. if (!FileManager.default.fileExists(atPath: watermarkPlistPath!)) {
  150. return false
  151. }
  152. let key: String = watermark.tag
  153. let dictionary = NSDictionary(contentsOfFile: watermarkPlistPath!)
  154. var newDictionary: NSMutableDictionary!
  155. if (dictionary != nil) {
  156. newDictionary = NSMutableDictionary(dictionary: dictionary!)
  157. } else {
  158. newDictionary = NSMutableDictionary()
  159. }
  160. newDictionary.removeObject(forKey: key)
  161. let result = newDictionary.write(toFile: watermarkPlistPath!, atomically: true)
  162. if (result) {
  163. if let filePath: String = watermark.imagePath {
  164. try?FileManager.default.removeItem(atPath: filePath)
  165. }
  166. if (self.watermarks.contains(watermark)) {
  167. self.watermarks.removeObject(watermark)
  168. }
  169. }
  170. return result
  171. }
  172. func removeAllWatermark() -> Bool {
  173. if (!FileManager.default.fileExists(atPath: watermarkPlistPath!)) {
  174. return false
  175. }
  176. let dictionary = NSDictionary(contentsOfFile: watermarkPlistPath!)
  177. var newDictionary: NSMutableDictionary!
  178. if (dictionary != nil) {
  179. newDictionary = NSMutableDictionary(dictionary: dictionary!)
  180. } else {
  181. newDictionary = NSMutableDictionary()
  182. }
  183. newDictionary.removeAllObjects()
  184. let result = newDictionary.write(toFile: watermarkPlistPath!, atomically: true)
  185. if (result) {
  186. self.watermarks.removeAll()
  187. }
  188. return result
  189. }
  190. //MARK: - private
  191. func setDictToWatermarK(dict: NSDictionary, _ model: KMWatermarkModel) {
  192. model.watermarkType = .text
  193. if let typeIndex = dict.object(forKey: KMWatermarkKey.watermarkType.rawValue) as? AnyObject {
  194. if let rawValue = typeIndex as? Int {
  195. model.watermarkType = CPDFWatermarkType(rawValue: rawValue) ?? .text
  196. } else if let rawValue = typeIndex as? String, let rawIndex = Int(rawValue) {
  197. model.watermarkType = CPDFWatermarkType(rawValue: rawIndex) ?? .text
  198. }
  199. }
  200. model.text = (dict.object(forKey: KMWatermarkKey.text.rawValue) as? String)
  201. model.fontName = (dict.object(forKey: KMWatermarkKey.textFontName.rawValue) as? String) ?? ""
  202. model.fontStyle = (dict.object(forKey: KMWatermarkKey.textfontStyle.rawValue) as? String) ?? ""
  203. model.fontSize = (dict.object(forKey: KMWatermarkKey.textFontSize.rawValue) as? CGFloat) ?? 12
  204. if let pathValue = dict.object(forKey: KMWatermarkKey.imagePath.rawValue) {
  205. let path = watermarkFolderPath?.stringByAppendingPathComponent(pathValue as! String)
  206. if (FileManager.default.fileExists(atPath: path!)) {
  207. model.imagePath = path ?? ""
  208. }
  209. }
  210. model.isScale = (dict.object(forKey: KMWatermarkKey.isScale.rawValue) as? Bool) ?? false
  211. model.scale = (dict.object(forKey: KMWatermarkKey.scale.rawValue) as? CGFloat) ?? 1
  212. model.rotation = dict.object(forKey: KMWatermarkKey.rotate.rawValue) as? CGFloat ?? 0
  213. model.opacity = (dict.object(forKey: KMWatermarkKey.opacity.rawValue) as? CGFloat) ?? 1
  214. model.verticalPosition = (dict.object(forKey: KMWatermarkKey.verticalMode.rawValue) as? CPDFWatermarkVerticalPosition) ?? .center
  215. model.ty = dict.object(forKey: KMWatermarkKey.verticalSpace.rawValue) as? CGFloat ?? 0
  216. model.horizontalPosition = (dict.object(forKey: KMWatermarkKey.horizontalMode.rawValue) as? CPDFWatermarkHorizontalPosition) ?? .center
  217. model.tx = dict.object(forKey: KMWatermarkKey.horizontalSpace.rawValue) as? CGFloat ?? 0
  218. if let textColorKey = dict.object(forKey: KMWatermarkKey.textColor.rawValue) as? String {
  219. model.textColor = NSColor.km_init(hex: textColorKey)
  220. } else {
  221. let red: CGFloat = dict.object(forKey: KMWatermarkKey.red.rawValue) as? CGFloat ?? 0
  222. let green: CGFloat = dict.object(forKey: KMWatermarkKey.green.rawValue) as? CGFloat ?? 0
  223. let blue: CGFloat = dict.object(forKey: KMWatermarkKey.blue.rawValue) as? CGFloat ?? 0
  224. model.textColor = NSColor(red: red, green: green, blue: blue, alpha: 1.0)
  225. }
  226. model.isFront = (dict.object(forKey: KMWatermarkKey.isFront.rawValue) as? Bool) ?? false
  227. model.isTilePage = (dict.object(forKey: KMWatermarkKey.isTile.rawValue) as? Bool) ?? false
  228. model.horizontalSpacing = (dict.object(forKey: KMWatermarkKey.tileHorizontalSpace.rawValue) as? CGFloat) ?? 0
  229. model.verticalSpacing = (dict.object(forKey: KMWatermarkKey.tileVerticalSpace.rawValue) as? CGFloat) ?? 0
  230. model.tag = (dict.object(forKey: KMWatermarkKey.tag.rawValue) as? String) ?? ""
  231. model.watermarkName = (dict.object(forKey: KMWatermarkKey.watermarkName.rawValue) as? String) ?? ""
  232. }
  233. //MARK: - Parse
  234. func parseWaterMark(model: KMWatermarkModel) -> Dictionary<String, Any> {
  235. var dict: [String : Any] = [:]
  236. if model.watermarkType == .text {
  237. dict[KMWatermarkKey.watermarkType.rawValue] = NSNumber(value: 0)
  238. } else if model.watermarkType == .image {
  239. dict[KMWatermarkKey.watermarkType.rawValue] = NSNumber(value: 1)
  240. }
  241. if let text = model.text {
  242. dict[KMWatermarkKey.text.rawValue] = text
  243. }
  244. dict[KMWatermarkKey.textFontName.rawValue] = model.fontName
  245. dict[KMWatermarkKey.textfontStyle.rawValue] = model.fontStyle
  246. dict[KMWatermarkKey.textFontSize.rawValue] = model.fontSize
  247. if let imagePath = model.imagePath {
  248. dict[KMWatermarkKey.imagePath.rawValue] = imagePath
  249. }
  250. dict[KMWatermarkKey.isFront.rawValue] = model.isFront
  251. dict[KMWatermarkKey.isScale.rawValue] = model.isScale
  252. dict[KMWatermarkKey.scale.rawValue] = model.scale
  253. dict[KMWatermarkKey.opacity.rawValue] = model.opacity
  254. dict[KMWatermarkKey.rotate.rawValue] = model.rotation
  255. dict[KMWatermarkKey.verticalMode.rawValue] = model.verticalPosition.rawValue
  256. dict[KMWatermarkKey.verticalSpace.rawValue] = model.ty
  257. dict[KMWatermarkKey.horizontalMode.rawValue] = model.horizontalPosition.rawValue
  258. dict[KMWatermarkKey.horizontalSpace.rawValue] = model.tx
  259. dict[KMWatermarkKey.textColor.rawValue] = model.textColor.toHex()
  260. dict[KMWatermarkKey.isTile.rawValue] = model.isTilePage
  261. dict[KMWatermarkKey.tileVerticalSpace.rawValue] = model.verticalSpacing
  262. dict[KMWatermarkKey.tileHorizontalSpace.rawValue] = model.horizontalSpacing
  263. dict[KMWatermarkKey.tag.rawValue] = model.tag
  264. dict[KMWatermarkKey.watermarkName.rawValue] = model.watermarkName
  265. return dict
  266. }
  267. private func parseDictionary(dict: NSDictionary) -> KMWatermarkModel {
  268. let model = KMWatermarkModel()
  269. if let type = dict.object(forKey: KMWatermarkKey.watermarkType.rawValue) {
  270. if let data = type as? Int {
  271. model.watermarkType = CPDFWatermarkType(rawValue: data) ?? .text
  272. } else if let data = type as? String, let value = Int(data), value < 2 {
  273. model.watermarkType = CPDFWatermarkType(rawValue: value) ?? .text
  274. } else {
  275. model.watermarkType = .text
  276. }
  277. } else {
  278. model.watermarkType = .text
  279. }
  280. model.text = (dict.object(forKey: KMWatermarkKey.text.rawValue) as? String)
  281. model.fontName = (dict.object(forKey: KMWatermarkKey.textFontName.rawValue) as? String) ?? ""
  282. model.fontStyle = (dict.object(forKey: KMWatermarkKey.textfontStyle.rawValue) as? String) ?? ""
  283. model.fontSize = (dict.object(forKey: KMWatermarkKey.textFontSize.rawValue) as? CGFloat) ?? 12
  284. if let pathValue = dict.object(forKey: KMWatermarkKey.imagePath.rawValue) {
  285. model.imagePath = pathValue as? String
  286. }
  287. model.isScale = (dict.object(forKey: KMWatermarkKey.isScale.rawValue) as? Bool) ?? false
  288. model.scale = (dict.object(forKey: KMWatermarkKey.scale.rawValue) as? CGFloat) ?? 1
  289. model.rotation = dict.object(forKey: KMWatermarkKey.rotate.rawValue) as? CGFloat ?? 0
  290. model.opacity = (dict.object(forKey: KMWatermarkKey.opacity.rawValue) as? CGFloat) ?? 1
  291. model.verticalPosition = (dict.object(forKey: KMWatermarkKey.verticalMode.rawValue) as? CPDFWatermarkVerticalPosition) ?? .center
  292. model.ty = dict.object(forKey: KMWatermarkKey.verticalSpace.rawValue) as? CGFloat ?? 0
  293. model.horizontalPosition = (dict.object(forKey: KMWatermarkKey.horizontalMode.rawValue) as? CPDFWatermarkHorizontalPosition) ?? .center
  294. model.tx = dict.object(forKey: KMWatermarkKey.horizontalSpace.rawValue) as? CGFloat ?? 0
  295. if let textColorKey = dict.object(forKey: KMWatermarkKey.textColor.rawValue) as? String {
  296. model.textColor = NSColor.km_init(hex: textColorKey)
  297. } else {
  298. let red: CGFloat = dict.object(forKey: KMWatermarkKey.red.rawValue) as? CGFloat ?? 0
  299. let green: CGFloat = dict.object(forKey: KMWatermarkKey.green.rawValue) as? CGFloat ?? 0
  300. let blue: CGFloat = dict.object(forKey: KMWatermarkKey.blue.rawValue) as? CGFloat ?? 0
  301. model.textColor = NSColor(red: red, green: green, blue: blue, alpha: 1.0)
  302. }
  303. model.isFront = (dict.object(forKey: KMWatermarkKey.isFront.rawValue) as? Bool) ?? false
  304. model.isTilePage = (dict.object(forKey: KMWatermarkKey.isTile.rawValue) as? Bool) ?? false
  305. model.horizontalSpacing = (dict.object(forKey: KMWatermarkKey.tileHorizontalSpace.rawValue) as? CGFloat) ?? 0
  306. model.verticalSpacing = (dict.object(forKey: KMWatermarkKey.tileVerticalSpace.rawValue) as? CGFloat) ?? 0
  307. model.tag = (dict.object(forKey: KMWatermarkKey.tag.rawValue) as? String) ?? ""
  308. model.watermarkName = (dict.object(forKey: KMWatermarkKey.watermarkName.rawValue) as? String) ?? ""
  309. return model
  310. }
  311. //MARK: - Getter
  312. func drawImageAtpageRect(rect: NSRect, data: KMWatermarkModel) -> NSImage? {
  313. var size = NSZeroSize
  314. let text: String = data.text ?? ""
  315. if data.watermarkType == .image {
  316. if let image = data.image() {
  317. size = image.size
  318. size.width *= data.scale
  319. size.height *= data.scale
  320. }
  321. } else if data.watermarkType == .text {
  322. var font = NSFont.systemFont(ofSize: 52)
  323. if data.isTilePage {
  324. font = NSFont.systemFont(ofSize: data.fontSize)
  325. }
  326. let style = NSMutableParagraphStyle()
  327. style.alignment = .center
  328. style.lineBreakMode = .byCharWrapping
  329. let attributes: [NSAttributedString.Key: Any] = [ .paragraphStyle: style, .font: font ]
  330. size = text.boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude), options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: attributes).size
  331. }
  332. let radian = data.rotation * (CGFloat.pi/180)
  333. let t = CGAffineTransform(rotationAngle: radian)
  334. var newRect = rect
  335. if !data.isTilePage {
  336. newRect = CGRect(x: 0, y: 0, width: size.width + 40, height: size.height + 40).applying(t)
  337. }
  338. let image = NSImage(size: newRect.size)
  339. image.lockFocus()
  340. NSGraphicsContext.current?.imageInterpolation = .high
  341. NSGraphicsContext.saveGraphicsState()
  342. NSColor.clear.set()
  343. rect.fill()
  344. NSGraphicsContext.restoreGraphicsState()
  345. guard let context = NSGraphicsContext.current?.cgContext else { return nil }
  346. let imageSize = newRect.size
  347. NSGraphicsContext.current = NSGraphicsContext(cgContext: context, flipped: false)
  348. NSGraphicsContext.saveGraphicsState()
  349. if data.watermarkType == .image {
  350. guard let image = data.image() else { return nil }
  351. var size = image.size
  352. size.width *= data.scale
  353. size.height *= data.scale
  354. let width = sqrt(image.size.height * image.size.height + image.size.width * image.size.width)
  355. let newRect = CGRect(x: -(width - image.size.width)/2, y: -(width - image.size.height)/2, width: width, height: width)
  356. let new_w = newRect.size.width
  357. let new_h = newRect.size.height
  358. let radian = data.rotation * (CGFloat.pi / 180)
  359. let t = CGAffineTransform(rotationAngle: radian)
  360. if data.isTilePage {
  361. context.translateBy(x: image.size.width/2, y: image.size.height/2)
  362. context.concatenate(t)
  363. context.translateBy(x: -(image.size.width/2), y: -(image.size.height/2))
  364. let verticalWidth = size.width + data.horizontalSpacing * data.scale
  365. let horizontalHeight = size.height + data.verticalSpacing * data.scale
  366. let line: Int = Int((new_h - data.verticalSpacing * data.scale)/horizontalHeight + 1)
  367. let row: Int = Int((new_w - data.horizontalSpacing * data.scale) / verticalWidth + 1)
  368. let point = CGPoint(x: image.size.width/2 - size.width/2 + data.tx*data.scale, y:image.size.height/2 - size.height/2 + data.ty * data.scale)
  369. for i in 0..<line/2+1 {
  370. for j in 0..<row {
  371. let area = CGRect(x: point.x + CGFloat(j) * verticalWidth, y: point.y + CGFloat(i) * horizontalHeight, width: size.width, height: size.height)
  372. image.draw(in: area, from: NSZeroRect, operation: .sourceOver, fraction: data.opacity)
  373. }
  374. }
  375. for i in 1..<line/2+1 {
  376. for j in 0..<row {
  377. let area = CGRect(x: point.x + CGFloat(j) * verticalWidth, y: point.y - CGFloat(i) * horizontalHeight, width: size.width, height: size.height)
  378. image.draw(in: area, from: NSZeroRect, operation: .sourceOver, fraction: data.opacity)
  379. }
  380. }
  381. for i in 0..<line/2+1 {
  382. for j in 1..<row {
  383. let area = CGRect(x: point.x - CGFloat(j) * verticalWidth, y: point.y + CGFloat(i) * horizontalHeight, width: size.width, height: size.height)
  384. image.draw(in: area, from: NSZeroRect, operation: .sourceOver, fraction: data.opacity)
  385. }
  386. }
  387. for i in 1..<(line/2 + 1) {
  388. for j in 1..<row {
  389. let area = CGRect(x: point.x - CGFloat(j)*verticalWidth, y: point.y - CGFloat(i)*horizontalHeight, width: size.width, height: size.height)
  390. image.draw(in: area, from: NSZeroRect, operation: .sourceOver, fraction: data.opacity)
  391. }
  392. }
  393. } else {
  394. var size = image.size
  395. size.width *= data.scale
  396. size.height *= data.scale
  397. let radian = data.rotation * (CGFloat.pi / 180)
  398. let t = CGAffineTransform(rotationAngle: radian)
  399. var imageRect = CGRect(origin: .zero, size: size).applying(t)
  400. if data.verticalPosition == .bottom {
  401. imageRect.origin.y = imageSize.height - imageRect.size.height
  402. } else if data.verticalPosition == .center {
  403. imageRect.origin.y = (imageSize.height - imageRect.size.height) / 2.0
  404. } else {
  405. imageRect.origin.y = 0
  406. }
  407. if data.horizontalPosition == .left {
  408. imageRect.origin.x = 0
  409. } else if data.horizontalPosition == .center {
  410. imageRect.origin.x = (imageSize.width - imageRect.size.width) / 2.0
  411. } else {
  412. imageRect.origin.x = imageSize.width - imageRect.size.width
  413. }
  414. let contextCenter = CGPoint(x: imageRect.midX, y: imageRect.midY)
  415. context.translateBy(x: contextCenter.x, y: contextCenter.y)
  416. context.rotate(by: radian)
  417. context.translateBy(x: -contextCenter.x, y: -contextCenter.y)
  418. image.draw(in: CGRect(x: imageRect.origin.x+(imageRect.size.width-size.width)/2.0, y: imageRect.origin.y+(imageRect.size.height-size.height)/2.0, width: size.width, height: size.height), from: NSZeroRect, operation: .sourceOver, fraction: data.opacity)
  419. }
  420. }else if text.count > 0 {
  421. var font = NSFont.systemFont(ofSize: 52)
  422. if data.isTilePage {
  423. font = NSFont.systemFont(ofSize: data.fontSize)
  424. }
  425. var color = data.textColor
  426. var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0
  427. color.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: nil)
  428. color = NSColor.init(calibratedRed: red, green: green, blue: blue, alpha: data.opacity)
  429. size = .zero
  430. let alpha = data.opacity
  431. let tileHorizontalSpace = data.horizontalSpacing
  432. let tileVerticalSpace = data.verticalSpacing
  433. let horizontalSpace = data.tx
  434. let verticalSpace = data.ty
  435. let style = NSMutableParagraphStyle()
  436. style.alignment = .center
  437. style.lineBreakMode = .byCharWrapping
  438. let attributes: [NSAttributedString.Key: Any] = [ .paragraphStyle: style, .foregroundColor: NSColor(calibratedRed: red, green: green, blue: blue, alpha: alpha), .font: font ]
  439. size = text.boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude), options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: attributes).size
  440. let textRect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
  441. if data.isTilePage {
  442. let width = sqrt(image.size.height * image.size.height + image.size.width * image.size.width)
  443. let newRect = CGRect(x: -(width - image.size.width) / 2, y: -(width - image.size.height) / 2, width: width, height: width)
  444. let new_w = newRect.size.width
  445. let new_h = newRect.size.height
  446. context.translateBy(x: image.size.width / 2, y: image.size.height / 2)
  447. context.concatenate(CGAffineTransform(rotationAngle: radian))
  448. context.translateBy(x: -(image.size.width / 2), y: -(image.size.height / 2))
  449. let verticalWidth = size.width + tileHorizontalSpace / 3.0
  450. let horizontalHeight = size.height + tileVerticalSpace / 3.0
  451. let line: Int = Int((new_h - tileHorizontalSpace / 3.0) / horizontalHeight + 1)
  452. let row: Int = Int((new_w - tileVerticalSpace / 3.0) / verticalWidth + 1)
  453. let point = CGPoint(x: image.size.width / 2 - size.width / 2 + horizontalSpace / 3.0, y: image.size.height / 2 - size.height / 2 + verticalSpace / 3.0)
  454. for i in 0..<line {
  455. for j in 0..<row {
  456. let drawRect = CGRect(x: point.x + CGFloat(j) * verticalWidth, y: point.y + CGFloat(i) * horizontalHeight, width: size.width, height: size.height)
  457. text.draw(in: drawRect, withAttributes: attributes)
  458. }
  459. }
  460. for i in 1..<line {
  461. for j in 0..<row {
  462. let drawRect = CGRect(x: point.x + CGFloat(j) * verticalWidth, y: point.y - CGFloat(i) * horizontalHeight, width: size.width, height: size.height)
  463. text.draw(in: drawRect, withAttributes: attributes)
  464. }
  465. }
  466. for i in 0..<line {
  467. for j in 1..<row {
  468. let drawRect = CGRect(x: point.x - CGFloat(j) * verticalWidth, y: point.y + CGFloat(i) * horizontalHeight, width: size.width, height: size.height)
  469. text.draw(in: drawRect, withAttributes: attributes)
  470. }
  471. }
  472. for i in 1..<line {
  473. for j in 1..<row {
  474. let drawRect = CGRect(x: point.x - CGFloat(j) * verticalWidth, y: point.y - CGFloat(i) * horizontalHeight, width: size.width, height: size.height)
  475. text.draw(in: drawRect, withAttributes: attributes)
  476. }
  477. }
  478. } else {
  479. var textRect = textRect
  480. if data.verticalPosition == .bottom {
  481. textRect.origin.y = imageSize.height - textRect.size.height
  482. } else if data.verticalPosition == .center {
  483. textRect.origin.y = (imageSize.height - textRect.size.height) / 2.0
  484. } else {
  485. textRect.origin.y = 0
  486. }
  487. if data.horizontalPosition == .left {
  488. textRect.origin.x = 0
  489. } else if data.horizontalPosition == .center {
  490. textRect.origin.x = (imageSize.width - textRect.size.width) / 2.0
  491. } else {
  492. textRect.origin.x = imageSize.width - textRect.size.width
  493. }
  494. let contextCenter = CGPoint(x: textRect.midX, y: textRect.midY)
  495. context.translateBy(x: contextCenter.x, y: contextCenter.y)
  496. context.rotate(by: radian)
  497. context.translateBy(x: -contextCenter.x, y: -contextCenter.y)
  498. (data.text ?? "").draw(in: CGRect(x: textRect.origin.x + (textRect.size.width - size.width) / 2.0, y: textRect.origin.y + (textRect.size.height - size.height) / 2.0, width: size.width, height: size.height), withAttributes: attributes)
  499. }
  500. }
  501. NSGraphicsContext.restoreGraphicsState()
  502. NSGraphicsContext.current?.imageInterpolation = .default
  503. image.unlockFocus()
  504. return image
  505. }
  506. class func getFontSize() -> [String] {
  507. return ["6","8","10","12","14",
  508. "16","18","20","22","24",
  509. "26","28","30","32","34",
  510. "36","40","48","64","80",
  511. "96","112"]
  512. }
  513. func fetchAvailableName() -> String {
  514. var availableIndex: Int = 0
  515. let watermark = "Watermark"
  516. for model in self.watermarks {
  517. let watermarkID = model.tag
  518. if (watermarkID.hasPrefix(watermark)) {
  519. let indexString: String = (watermarkID.components(separatedBy: watermark).last ?? "0")
  520. let index: Int = Int(indexString) ?? 0
  521. if (index >= availableIndex) {
  522. availableIndex = index + 1
  523. }
  524. }
  525. }
  526. return "\(watermark)\(availableIndex)"
  527. }
  528. //MARK: - Compare
  529. class func compareIsChangedModel(_ model: KMWatermarkModel, withDict dict: NSDictionary) -> Bool {
  530. if let value = dict["fontName"] {
  531. if model.fontName != (value as! String) {
  532. return true
  533. }
  534. }
  535. if let value = dict.object(forKey: KMWatermarkKey.text.rawValue) {
  536. if model.text != (value as! String) {
  537. return true
  538. }
  539. }
  540. if let value = dict.object(forKey: KMWatermarkKey.textFontName.rawValue) {
  541. if model.fontName != (value as! String) {
  542. return true
  543. }
  544. }
  545. if let value = dict.object(forKey: KMWatermarkKey.textfontStyle.rawValue) {
  546. if model.fontStyle != (value as! String) {
  547. return true
  548. }
  549. }
  550. if let value = dict.object(forKey: KMWatermarkKey.textFontSize.rawValue) {
  551. if model.fontSize != (value as! CGFloat) {
  552. return true
  553. }
  554. }
  555. if let value = dict.object(forKey: KMWatermarkKey.imagePath.rawValue) {
  556. if model.imagePath != (value as! String) {
  557. return true
  558. }
  559. }
  560. if let value = dict.object(forKey: KMWatermarkKey.isScale.rawValue) {
  561. if model.isScale != (value as! Bool) {
  562. return true
  563. }
  564. }
  565. if let value = dict.object(forKey: KMWatermarkKey.scale.rawValue) {
  566. if model.scale != (value as! CGFloat) {
  567. return true
  568. }
  569. }
  570. if let value = dict.object(forKey: KMWatermarkKey.rotate.rawValue) {
  571. if model.rotation != (value as! CGFloat) {
  572. return true
  573. }
  574. }
  575. if let value = dict.object(forKey: KMWatermarkKey.opacity.rawValue) {
  576. if model.opacity != (value as! CGFloat) {
  577. return true
  578. }
  579. }
  580. if let value = dict.object(forKey: KMWatermarkKey.verticalMode.rawValue) {
  581. if model.verticalPosition.rawValue != (value as! Int) {
  582. return true
  583. }
  584. }
  585. if let value = dict.object(forKey: KMWatermarkKey.verticalSpace.rawValue) {
  586. if model.ty != (value as! CGFloat) {
  587. return true
  588. }
  589. }
  590. if let value = dict.object(forKey: KMWatermarkKey.horizontalMode.rawValue) {
  591. if model.horizontalPosition.rawValue != (value as! Int) {
  592. return true
  593. }
  594. }
  595. if let value = dict.object(forKey: KMWatermarkKey.horizontalSpace.rawValue) {
  596. if model.tx != (value as! CGFloat) {
  597. return true
  598. }
  599. }
  600. if let value = dict.object(forKey: KMWatermarkKey.textColor.rawValue) {
  601. var modelColorText = model.textColor.colorToHexString()
  602. if modelColorText.count > 7 {
  603. modelColorText = modelColorText.substring(to: 7)
  604. }
  605. if var valueString = value as? String {
  606. if valueString.count > 7 {
  607. valueString = valueString.substring(to: 7)
  608. }
  609. if valueString != modelColorText {
  610. return true
  611. }
  612. }
  613. }
  614. if let value = dict.object(forKey: KMWatermarkKey.isFront.rawValue) {
  615. if model.isFront != (value as! Bool) {
  616. return true
  617. }
  618. }
  619. if let value = dict.object(forKey: KMWatermarkKey.isTile.rawValue) {
  620. if model.isTilePage != (value as! Bool) {
  621. return true
  622. }
  623. }
  624. if let value = dict.object(forKey: KMWatermarkKey.tileHorizontalSpace.rawValue) {
  625. if model.horizontalSpacing != (value as! CGFloat) {
  626. return true
  627. }
  628. }
  629. if let value = dict.object(forKey: KMWatermarkKey.tileVerticalSpace.rawValue) {
  630. if model.verticalSpacing != (value as! CGFloat) {
  631. return true
  632. }
  633. }
  634. return false
  635. }
  636. }