KMWatermarkManager.swift 33 KB

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