KMWatermarkPDFView_OC.m 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. //
  2. // KMWatermarkPDFView.m
  3. // PDF Reader Pro Edition
  4. //
  5. // Created by zhipeng jiang on 2020/11/17.
  6. //
  7. #import "KMWatermarkPDFView_OC.h"
  8. #if VERSION_DMG
  9. #import <PDF_Master-Swift.h>
  10. #else
  11. #import <PDF_Master-Swift.h>
  12. #endif
  13. @interface KMWatermarkPDFView_OC ()
  14. @property (nonatomic, strong) KMWatermarkModel *watermark;
  15. @property (nonatomic, strong) KMBackgroundModel *background;
  16. @property (nonatomic, strong) KMBatesModel *bates;
  17. @property (nonatomic, strong) KMHeaderFooterModel *headerFooter;
  18. @end
  19. @implementation KMWatermarkPDFView_OC
  20. - (void)setModel:(id)model {
  21. _model = model;
  22. if ([model isKindOfClass:[KMBatesModel class]]) {
  23. self.bates = model;
  24. } else if ([model isKindOfClass:[KMWatermarkModel class]]) {
  25. self.watermark = model;
  26. } else if ([model isKindOfClass:[KMBackgroundModel class]]) {
  27. self.background = model;
  28. } else if ([model isKindOfClass:[KMHeaderFooterModel class]]) {
  29. self.headerFooter = model;
  30. } else {
  31. self.bates = nil;
  32. self.watermark = nil;
  33. self.background = nil;
  34. self.headerFooter = nil;
  35. }
  36. [self setNeedsDisplayForVisiblePages];
  37. }
  38. - (void)drawPage:(CPDFPage *)page toContext:(CGContextRef)context {
  39. if (self.watermark) {
  40. if (self.watermark.isFront) {
  41. [super drawPage:page toContext:context];
  42. [self drawWatermarkPage:page toContext:context];
  43. } else {
  44. [self drawWatermarkPage:page toContext:context];
  45. [super drawPage:page toContext:context];
  46. }
  47. } else if (self.background) {
  48. [self drawBackgroundPage:page toContext:context];
  49. [super drawPage:page toContext:context];
  50. } else if (self.headerFooter ){
  51. [super drawPage:page toContext:context];
  52. [self drawHeaderFooterPage:page toContext:context];
  53. } else if (self.bates) {
  54. [super drawPage:page toContext:context];
  55. [self drawBatesPage:page toContext:context];
  56. } else {
  57. [super drawPage:page toContext:context];
  58. }
  59. }
  60. - (void)drawWatermarkPage:(CPDFPage *)page toContext:(CGContextRef)context {
  61. NSRect pageBounds = [page boundsForBox:CPDFDisplayCropBox];
  62. CGFloat w = pageBounds.size.width;
  63. CGFloat h = pageBounds.size.height;
  64. CGFloat width = sqrt(pageBounds.size.height * pageBounds.size.height + pageBounds.size.width * pageBounds.size.width);
  65. CGRect newRect = CGRectMake(-(width - pageBounds.size.width)/2, -(width - pageBounds.size.height)/2, width, width);
  66. CGFloat new_w = newRect.size.width;
  67. CGFloat new_h = newRect.size.height;
  68. if (context) {
  69. [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO]];
  70. }
  71. [NSGraphicsContext saveGraphicsState];
  72. [page transformContext:context forBox:CPDFDisplayCropBox];
  73. if(self.watermark.pagesString.length > 0) {
  74. NSArray *array = [self.watermark.pagesString componentsSeparatedByString:@","];
  75. NSInteger index = [self.document indexForPage:page];
  76. if(![array containsObject:[NSString stringWithFormat:@"%ld",index]]) {
  77. return;
  78. }
  79. }
  80. if (self.watermark.text && self.watermark.text.length > 0) {
  81. NSFont *font = [NSFont fontWithName:@"Helvetica" size:self.watermark.getTextFontSize];
  82. NSColor *color = self.watermark.getTextColor ? : [NSColor blackColor];
  83. CGFloat red,green,blue;
  84. [[color colorUsingColorSpaceName:NSCalibratedRGBColorSpace] getRed:&red
  85. green:&green
  86. blue:&blue
  87. alpha:nil];
  88. color = [NSColor colorWithCalibratedRed:red green:green blue:blue alpha:self.watermark.opacity];
  89. NSSize size = NSZeroSize;
  90. NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
  91. [style setAlignment:NSTextAlignmentCenter];
  92. [style setLineBreakMode:NSLineBreakByCharWrapping];
  93. NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
  94. [dictionary setObject:style forKey:NSParagraphStyleAttributeName];
  95. [dictionary setObject:color forKey:NSForegroundColorAttributeName];
  96. [dictionary setObject:font forKey:NSFontAttributeName];
  97. size = [self.watermark.text boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
  98. options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  99. attributes:dictionary].size;
  100. CGFloat radian = self.watermark.rotation*(M_PI/180);
  101. CGAffineTransform t = CGAffineTransformRotate(CGAffineTransformIdentity, radian);
  102. CGRect rect = CGRectMake(0, 0, size.width, size.height);
  103. if(self.watermark.isTilePage) {
  104. CGContextTranslateCTM(context, w/2,h/2);
  105. CGContextConcatCTM(context, t);
  106. CGContextTranslateCTM(context, -(w/2), - (h/2));
  107. CGFloat verticalWidth = size.width + self.watermark.tileHorizontalSpace;
  108. CGFloat horizontalHeight = size.height + self.watermark.tileVerticalSpace;
  109. NSInteger line = (new_h - self.watermark.tileVerticalSpace )/ horizontalHeight + 1 ; //多少行
  110. NSInteger row = (new_w - self.watermark.tileHorizontalSpace) / verticalWidth + 1 ;
  111. CGPoint point = CGPointMake(w/2 - size.width/2+self.watermark.horizontalSpace, h/2 - size.height/2+self.watermark.verticalSpace);
  112. for (int i = 0; i < line; i ++) {
  113. for (int j = 0; j < row ; j ++) {
  114. [self.watermark.text drawInRect:CGRectMake(point.x + j * verticalWidth, point.y + i*horizontalHeight, size.width, size.height) withAttributes:dictionary];
  115. }
  116. }
  117. for (int i = 1; i < line; i ++) {
  118. for (int j = 0; j < row ; j ++) {
  119. [self.watermark.text drawInRect:CGRectMake(point.x + j * verticalWidth, point.y - i*horizontalHeight, size.width, size.height) withAttributes:dictionary];
  120. }
  121. }
  122. for (int i = 0; i < line; i ++) {
  123. for (int j = 1; j < row ; j ++) {
  124. [self.watermark.text drawInRect:CGRectMake(point.x -j * verticalWidth, point.y + i*horizontalHeight, size.width, size.height) withAttributes:dictionary];
  125. }
  126. }
  127. for (int i = 1; i < line; i ++) {
  128. for (int j = 1; j < row ; j ++) {
  129. [self.watermark.text drawInRect:CGRectMake(point.x - j * verticalWidth, point.y - i*horizontalHeight, size.width, size.height) withAttributes:dictionary];
  130. }
  131. }
  132. } else {
  133. if (self.watermark.verticalMode == 0) {
  134. rect.origin.y = pageBounds.size.height-rect.size.height;
  135. } else if (self.watermark.verticalMode == 1) {
  136. rect.origin.y = (pageBounds.size.height-rect.size.height)/2.0;
  137. } else {
  138. rect.origin.y = 0;
  139. }
  140. if (self.watermark.horizontalMode == 0) {
  141. rect.origin.x = 0;
  142. } else if (self.watermark.horizontalMode == 1) {
  143. rect.origin.x = (pageBounds.size.width-rect.size.width)/2.0;
  144. } else {
  145. rect.origin.x = pageBounds.size.width-rect.size.width;
  146. }
  147. rect.origin.x += self.watermark.horizontalSpace;
  148. rect.origin.y += self.watermark.verticalSpace;
  149. CGPoint contextCenter = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
  150. CGContextTranslateCTM(context, contextCenter.x, contextCenter.y);
  151. CGContextRotateCTM(context, radian);
  152. CGContextTranslateCTM(context, -contextCenter.x, -contextCenter.y);
  153. [self.watermark.text drawInRect:rect
  154. withAttributes:dictionary];
  155. }
  156. } else if (self.watermark.image) {
  157. NSData * tiffData = [self.watermark.image TIFFRepresentation];
  158. NSBitmapImageRep * bitmap;
  159. bitmap = [NSBitmapImageRep imageRepWithData:tiffData];
  160. CIImage * ciImage = [[CIImage alloc] initWithBitmapImageRep:bitmap];
  161. NSSize size = [ciImage extent].size;
  162. size.width *= self.watermark.scale;
  163. size.height *= self.watermark.scale;
  164. CGFloat radian = self.watermark.rotation*(M_PI/180);
  165. CGAffineTransform t = CGAffineTransformRotate(CGAffineTransformIdentity, radian);
  166. CGRect rect = CGRectMake(0, 0, size.width, size.height);
  167. if(self.watermark.isTilePage) {
  168. CGContextTranslateCTM(context, w/2,h/2);
  169. CGContextConcatCTM(context, t);
  170. CGContextTranslateCTM(context, -(w/2), - (h/2));
  171. CGFloat verticalWidth = size.width + self.watermark.tileHorizontalSpace;
  172. CGFloat horizontalHeight = size.height + self.watermark.tileVerticalSpace;
  173. NSInteger line = (new_h - self.watermark.tileVerticalSpace )/ horizontalHeight + 1 ; //多少行
  174. NSInteger row = (new_w - self.watermark.tileHorizontalSpace) / verticalWidth + 1 ;
  175. CGPoint point = CGPointMake(w/2 - size.width/2, h/2 - size.height/2);
  176. for (int i = 0; i < line/2+1; i ++) {
  177. for (int j = 0; j < row ; j ++) {
  178. CGRect area = CGRectMake(point.x + j * verticalWidth, point.y + i*horizontalHeight, size.width,size.height);
  179. [self.watermark.image drawInRect:area
  180. fromRect:NSZeroRect
  181. operation:NSCompositeSourceOver
  182. fraction:self.watermark.opacity];
  183. }
  184. }
  185. for (int i = 1; i < line/2+1; i ++) {
  186. for (int j = 0; j < row ; j ++) {
  187. CGRect area = CGRectMake(point.x + j * verticalWidth, point.y - i*horizontalHeight, size.width,size.height);
  188. [self.watermark.image drawInRect:area
  189. fromRect:NSZeroRect
  190. operation:NSCompositeSourceOver
  191. fraction:self.watermark.opacity];
  192. }
  193. }
  194. for (int i = 0; i < line/2 +1; i ++) {
  195. for (int j = 1; j < row ; j ++) {
  196. CGRect area = CGRectMake(point.x - j * verticalWidth, point.y + i*horizontalHeight, size.width,size.height);
  197. [self.watermark.image drawInRect:area
  198. fromRect:NSZeroRect
  199. operation:NSCompositeSourceOver
  200. fraction:self.watermark.opacity];
  201. }
  202. }
  203. for (int i = 1; i < line/2 + 1; i ++) {
  204. for (int j = 1; j < row ; j ++) {
  205. CGRect area = CGRectMake(point.x - j * verticalWidth, point.y - i*horizontalHeight, size.width, size.height);
  206. [self.watermark.image drawInRect:area
  207. fromRect:NSZeroRect
  208. operation:NSCompositeSourceOver
  209. fraction:self.watermark.opacity];
  210. }
  211. }
  212. } else {
  213. if (self.watermark.verticalMode == 0) {
  214. rect.origin.y = pageBounds.size.height-rect.size.height;
  215. } else if (self.watermark.verticalMode == 1) {
  216. rect.origin.y = (pageBounds.size.height-rect.size.height)/2.0;
  217. } else {
  218. rect.origin.y = 0;
  219. }
  220. if (self.watermark.horizontalMode == 0) {
  221. rect.origin.x = 0;
  222. } else if (self.watermark.horizontalMode == 1) {
  223. rect.origin.x = (pageBounds.size.width-rect.size.width)/2.0;
  224. } else {
  225. rect.origin.x = pageBounds.size.width-rect.size.width;
  226. }
  227. rect.origin.x += self.watermark.horizontalSpace;
  228. rect.origin.y += self.watermark.verticalSpace;
  229. CGPoint contextCenter = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
  230. CGContextTranslateCTM(context, contextCenter.x, contextCenter.y);
  231. CGContextRotateCTM(context, radian);
  232. CGContextTranslateCTM(context, -contextCenter.x, -contextCenter.y);
  233. [self.watermark.image drawInRect:rect
  234. fromRect:NSZeroRect
  235. operation:NSCompositeSourceOver
  236. fraction:self.watermark.opacity];
  237. }
  238. }
  239. [NSGraphicsContext restoreGraphicsState];
  240. }
  241. - (void)drawBackgroundPage:(CPDFPage *)page toContext:(CGContextRef)context {
  242. NSRect pageBounds = [page boundsForBox:CPDFDisplayCropBox];
  243. if (context) {
  244. [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO]];
  245. }
  246. [NSGraphicsContext saveGraphicsState];
  247. [page transformContext:context forBox:CPDFDisplayCropBox];
  248. //self.background.color && self.background.color != [NSColor clearColor]
  249. if (self.background.type == KMBackgroundTypeColor) {
  250. NSSize size = pageBounds.size;
  251. size.width *= self.background.scale;
  252. size.height *= self.background.scale;
  253. CGFloat radian = self.background.rotation*(M_PI/180);
  254. CGAffineTransform t = CGAffineTransformRotate(CGAffineTransformIdentity, radian);
  255. CGRect rect = CGRectApplyAffineTransform(CGRectMake(0, 0, size.width, size.height), t);
  256. if (self.background.verticalMode == 0) {
  257. rect.origin.y = pageBounds.size.height-rect.size.height;
  258. } else if (self.background.verticalMode == 1) {
  259. rect.origin.y = (pageBounds.size.height-rect.size.height)/2.0;
  260. } else {
  261. rect.origin.y = 0;
  262. }
  263. if (self.background.horizontalMode == 0) {
  264. rect.origin.x = 0;
  265. } else if (self.background.horizontalMode == 1) {
  266. rect.origin.x = (pageBounds.size.width-rect.size.width)/2.0;
  267. } else {
  268. rect.origin.x = pageBounds.size.width-rect.size.width;
  269. }
  270. rect.origin.y += self.background.verticalSpace;
  271. rect.origin.x += self.background.horizontalSpace;
  272. CGPoint contextCenter = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
  273. CGContextTranslateCTM(context, contextCenter.x, contextCenter.y);
  274. CGContextRotateCTM(context, radian);
  275. CGContextTranslateCTM(context, -contextCenter.x, -contextCenter.y);
  276. // CGContextSetBlendMode(context, kCGBlendModeDestinationIn);
  277. CGFloat red,green,blue,alpha;
  278. [[self.background.color colorUsingColorSpaceName:NSCalibratedRGBColorSpace] getRed:&red green:&green blue:&blue alpha:&alpha];
  279. CGContextSetRGBFillColor(context, red, green, blue, self.background.opacity);
  280. CGContextFillRect(context, CGRectMake(rect.origin.x+(rect.size.width-size.width)/2.0,
  281. rect.origin.y+(rect.size.height-size.height)/2.0,
  282. size.width, size.height));
  283. } else if (self.background.type == KMBackgroundTypeFile) { /// self.background.image
  284. NSImage *image = self.background.image;
  285. NSSize size = image.size;;
  286. if ([self.background.imagePath.pathExtension.lowercaseString isEqualToString:@"pdf"] && [[NSFileManager defaultManager] fileExistsAtPath:self.background.imagePath]) {
  287. } else {
  288. size = CGSizeMake(size.width * 2, size.height * 2);
  289. }
  290. size.width *= self.background.scale;
  291. size.height *= self.background.scale;
  292. CGFloat radian = self.background.rotation*(M_PI/180);
  293. CGAffineTransform t = CGAffineTransformRotate(CGAffineTransformIdentity, radian);
  294. CGRect rect = CGRectApplyAffineTransform(CGRectMake(0, 0, size.width, size.height), t);
  295. if (self.background.verticalMode == 0) {
  296. rect.origin.y = pageBounds.size.height-rect.size.height;
  297. } else if (self.background.verticalMode == 1) {
  298. rect.origin.y = (pageBounds.size.height-rect.size.height)/2.0;
  299. } else {
  300. rect.origin.y = 0;
  301. }
  302. if (self.background.horizontalMode == 0) {
  303. rect.origin.x = 0;
  304. } else if (self.background.horizontalMode == 1) {
  305. rect.origin.x = (pageBounds.size.width-rect.size.width)/2.0;
  306. } else {
  307. rect.origin.x = pageBounds.size.width-rect.size.width;
  308. }
  309. rect.origin.y += self.background.verticalSpace;
  310. rect.origin.x += self.background.horizontalSpace;
  311. CGPoint contextCenter = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
  312. CGContextTranslateCTM(context, contextCenter.x, contextCenter.y);
  313. CGContextRotateCTM(context, radian);
  314. CGContextTranslateCTM(context, -contextCenter.x, -contextCenter.y);
  315. [image drawInRect:CGRectMake(rect.origin.x+(rect.size.width-size.width)/2.0,
  316. rect.origin.y+(rect.size.height-size.height)/2.0,
  317. size.width, size.height)
  318. fromRect:NSZeroRect
  319. operation:NSCompositeSourceOver
  320. fraction:self.background.opacity];
  321. }
  322. [NSGraphicsContext restoreGraphicsState];
  323. }
  324. - (void)drawHeaderFooterPage:(CPDFPage *)page toContext:(CGContextRef)context
  325. {
  326. NSRect pageBounds = [page boundsForBox:CPDFDisplayCropBox];
  327. [NSGraphicsContext saveGraphicsState];
  328. if (context) {
  329. [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO]];
  330. }
  331. [page transformContext:context forBox:CPDFDisplayCropBox];
  332. NSColor *color = self.headerFooter.getTextColor ? : [NSColor blackColor];
  333. NSFont *font = [NSFont boldSystemFontOfSize:self.headerFooter.getTextFontSize];
  334. NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
  335. [style setAlignment:NSTextAlignmentCenter];
  336. [style setLineBreakMode:NSLineBreakByCharWrapping];
  337. NSSize size = NSZeroSize;
  338. NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
  339. [dictionary setObject:style forKey:NSParagraphStyleAttributeName];
  340. [dictionary setObject:color forKey:NSForegroundColorAttributeName];
  341. [dictionary setObject:font forKey:NSFontAttributeName];
  342. NSInteger index = [self.document indexForPage:page];
  343. CGFloat topOffset = 0;
  344. CGFloat bottomOffset = 0;
  345. if (self.headerFooter.topLeftString && self.headerFooter.topLeftString.length > 0) {
  346. NSString *tString = [self replacingOldString:self.headerFooter.topLeftString currentPage:index] ;
  347. size = [tString boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
  348. options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  349. attributes:dictionary].size;
  350. CGFloat posY = MIN(pageBounds.size.height - self.headerFooter.topMargin, pageBounds.size.height - size.height);
  351. [tString drawInRect:CGRectMake(self.headerFooter.leftMargin,
  352. posY,
  353. size.width,
  354. size.height)
  355. withAttributes:dictionary];
  356. }
  357. if (self.headerFooter.topCenterString && self.headerFooter.topCenterString.length > 0) {
  358. NSString *tString = [self replacingOldString:self.headerFooter.topCenterString currentPage:index] ;
  359. size = [tString boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
  360. options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  361. attributes:dictionary].size;
  362. CGFloat posY = MIN(pageBounds.size.height - self.headerFooter.topMargin, pageBounds.size.height - size.height);
  363. [tString drawInRect:CGRectMake(pageBounds.size.width/2 - size.width/2,
  364. posY,
  365. size.width,
  366. size.height)
  367. withAttributes:dictionary];
  368. }
  369. if (self.headerFooter.topRightString && self.headerFooter.topRightString.length > 0) {
  370. NSString *tString = [self replacingOldString:self.headerFooter.topRightString currentPage:index] ;
  371. size = [tString boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
  372. options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  373. attributes:dictionary].size;
  374. CGFloat posY = MIN(pageBounds.size.height - self.headerFooter.topMargin, pageBounds.size.height - size.height);
  375. [tString drawInRect:CGRectMake(pageBounds.size.width -self.headerFooter.rightMargin - size.width,
  376. posY,
  377. size.width,
  378. size.height)
  379. withAttributes:dictionary];
  380. }
  381. if (self.headerFooter.bottomLeftString && self.headerFooter.bottomLeftString.length > 0) {
  382. NSString *tString = [self replacingOldString:self.headerFooter.bottomLeftString currentPage:index] ;
  383. size = [tString boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
  384. options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  385. attributes:dictionary].size;
  386. CGFloat posY = MAX(self.headerFooter.bottomMargin-size.height, 0);
  387. [tString drawInRect:CGRectMake(self.headerFooter.leftMargin,
  388. posY,
  389. size.width,
  390. size.height)
  391. withAttributes:dictionary];
  392. }
  393. if (self.headerFooter.bottomCenterString && self.headerFooter.bottomCenterString.length > 0) {
  394. NSString *tString = [self replacingOldString:self.headerFooter.bottomCenterString currentPage:index] ;
  395. size = [tString boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
  396. options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  397. attributes:dictionary].size;
  398. CGFloat posY = MAX(self.headerFooter.bottomMargin-size.height, 0);
  399. [tString drawInRect:CGRectMake(pageBounds.size.width/2 - size.width/2,
  400. posY,
  401. size.width,
  402. size.height)
  403. withAttributes:dictionary];
  404. }
  405. if (self.headerFooter.bottomRightString && self.headerFooter.bottomRightString.length > 0) {
  406. NSString *tString = [self replacingOldString:self.headerFooter.bottomRightString currentPage:index] ;
  407. size = [tString boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
  408. options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  409. attributes:dictionary].size;
  410. CGFloat posY = MAX(self.headerFooter.bottomMargin-size.height, 0);
  411. [tString drawInRect:CGRectMake(pageBounds.size.width - self.headerFooter.rightMargin - size.width,
  412. posY,
  413. size.width,
  414. size.height)
  415. withAttributes:dictionary];
  416. }
  417. CGContextSetStrokeColorWithColor(context, [NSColor colorWithRed:51.0/255.0 green:186.0/255.0 blue:234.0/255.0 alpha:1.0].CGColor);
  418. CGContextSetLineWidth(context, 1.0);
  419. CGContextMoveToPoint(context, 0, self.headerFooter.bottomMargin + bottomOffset);
  420. CGContextAddLineToPoint(context,pageBounds.size.width, self.headerFooter.bottomMargin + bottomOffset);
  421. CGContextMoveToPoint(context, self.headerFooter.leftMargin, 0);
  422. CGContextAddLineToPoint(context, self.headerFooter.leftMargin,pageBounds.size.height);
  423. CGContextMoveToPoint(context, pageBounds.size.width - self.headerFooter.rightMargin, 0);
  424. CGContextAddLineToPoint(context,pageBounds.size.width - self.headerFooter.rightMargin, pageBounds.size.height);
  425. CGContextMoveToPoint(context, 0, pageBounds.size.height - self.headerFooter.topMargin - topOffset);
  426. CGContextAddLineToPoint(context,pageBounds.size.width, pageBounds.size.height - self.headerFooter.topMargin - topOffset);
  427. CGFloat arr[] = {8,1};
  428. CGContextSetLineDash(context, 0, arr, 1);
  429. CGContextDrawPath(context, kCGPathStroke);
  430. [NSGraphicsContext restoreGraphicsState];
  431. }
  432. - (void)drawBatesPage:(CPDFPage *)page toContext:(CGContextRef)context
  433. {
  434. NSRect pageBounds = [page boundsForBox:CPDFDisplayCropBox];
  435. [NSGraphicsContext saveGraphicsState];
  436. if (context) {
  437. [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO]];
  438. }
  439. [page transformContext:context forBox:CPDFDisplayCropBox];
  440. NSColor *color = self.bates.getTextColor ? : [NSColor blackColor];
  441. NSFont *font = [NSFont boldSystemFontOfSize:self.bates.getTextFontSize];
  442. NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
  443. [style setAlignment:NSTextAlignmentCenter];
  444. [style setLineBreakMode:NSLineBreakByCharWrapping];
  445. NSSize size = NSZeroSize;
  446. NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
  447. [dictionary setObject:style forKey:NSParagraphStyleAttributeName];
  448. [dictionary setObject:color forKey:NSForegroundColorAttributeName];
  449. [dictionary setObject:font forKey:NSFontAttributeName];
  450. NSInteger index = [self.document indexForPage:page];
  451. CGFloat topOffset = 0;
  452. CGFloat bottomOffset = 0;
  453. if (self.bates.topLeftString && self.bates.topLeftString.length > 0) {
  454. NSString *tString = [self replacingOldString:self.bates.topLeftString currentPage:index] ;
  455. size = [tString boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
  456. options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  457. attributes:dictionary].size;
  458. CGFloat posY = MIN(pageBounds.size.height - self.bates.topMargin, pageBounds.size.height - size.height);
  459. [tString drawInRect:CGRectMake(self.bates.leftMargin,
  460. posY,
  461. size.width,
  462. size.height)
  463. withAttributes:dictionary];
  464. }
  465. if (self.bates.topCenterString && self.bates.topCenterString.length > 0) {
  466. NSString *tString = [self replacingOldString:self.bates.topCenterString currentPage:index] ;
  467. size = [tString boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
  468. options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  469. attributes:dictionary].size;
  470. CGFloat posY = MIN(pageBounds.size.height - self.bates.topMargin, pageBounds.size.height - size.height);
  471. [tString drawInRect:CGRectMake(pageBounds.size.width/2 - size.width/2,
  472. posY,
  473. size.width,
  474. size.height)
  475. withAttributes:dictionary];
  476. }
  477. if (self.bates.topRightString && self.bates.topRightString.length > 0) {
  478. NSString *tString = [self replacingOldString:self.bates.topRightString currentPage:index] ;
  479. size = [tString boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
  480. options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  481. attributes:dictionary].size;
  482. CGFloat posY = MIN(pageBounds.size.height - self.bates.topMargin, pageBounds.size.height - size.height);
  483. [tString drawInRect:CGRectMake(pageBounds.size.width -self.bates.rightMargin - size.width,
  484. posY,
  485. size.width,
  486. size.height)
  487. withAttributes:dictionary];
  488. }
  489. if (self.bates.bottomLeftString && self.bates.bottomLeftString.length > 0) {
  490. NSString *tString = [self replacingOldString:self.bates.bottomLeftString currentPage:index] ;
  491. size = [tString boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
  492. options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  493. attributes:dictionary].size;
  494. CGFloat posY = MAX(self.bates.bottomMargin-size.height, 0);
  495. [tString drawInRect:CGRectMake(self.bates.leftMargin,
  496. posY,
  497. size.width,
  498. size.height)
  499. withAttributes:dictionary];
  500. }
  501. if (self.bates.bottomCenterString && self.bates.bottomCenterString.length > 0) {
  502. NSString *tString = [self replacingOldString:self.bates.bottomCenterString currentPage:index] ;
  503. size = [tString boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
  504. options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  505. attributes:dictionary].size;
  506. CGFloat posY = MAX(self.bates.bottomMargin-size.height, 0);
  507. [tString drawInRect:CGRectMake(pageBounds.size.width/2 - size.width/2,
  508. posY,
  509. size.width,
  510. size.height)
  511. withAttributes:dictionary];
  512. }
  513. if (self.bates.bottomRightString && self.bates.bottomRightString.length > 0) {
  514. NSString *tString = [self replacingOldString:self.bates.bottomRightString currentPage:index] ;
  515. size = [tString boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
  516. options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  517. attributes:dictionary].size;
  518. CGFloat posY = MAX(self.bates.bottomMargin-size.height, 0);
  519. [tString drawInRect:CGRectMake(pageBounds.size.width - self.bates.rightMargin - size.width,
  520. posY,
  521. size.width,
  522. size.height)
  523. withAttributes:dictionary];
  524. }
  525. CGContextSetStrokeColorWithColor(context, [NSColor colorWithRed:51.0/255.0 green:186.0/255.0 blue:234.0/255.0 alpha:1.0].CGColor);
  526. CGContextSetLineWidth(context, 1.0);
  527. CGContextMoveToPoint(context, 0, self.bates.bottomMargin + bottomOffset);
  528. CGContextAddLineToPoint(context,pageBounds.size.width, self.bates.bottomMargin + bottomOffset);
  529. CGContextMoveToPoint(context, self.bates.leftMargin, 0);
  530. CGContextAddLineToPoint(context, self.bates.leftMargin,pageBounds.size.height);
  531. CGContextMoveToPoint(context, pageBounds.size.width - self.bates.rightMargin, 0);
  532. CGContextAddLineToPoint(context,pageBounds.size.width - self.bates.rightMargin, pageBounds.size.height);
  533. CGContextMoveToPoint(context, 0, pageBounds.size.height - self.bates.topMargin - topOffset);
  534. CGContextAddLineToPoint(context,pageBounds.size.width, pageBounds.size.height - self.bates.topMargin - topOffset);
  535. CGFloat arr[] = {8,1};
  536. CGContextSetLineDash(context, 0, arr, 1);
  537. CGContextDrawPath(context, kCGPathStroke);
  538. [NSGraphicsContext restoreGraphicsState];
  539. }
  540. - (NSString *)replacingOldString:(NSString *)oldString currentPage:(NSInteger)page
  541. {
  542. if (!oldString) {
  543. return @"";
  544. }
  545. NSString * newString = oldString;
  546. NSString * startString = @"";
  547. if (self.bates) {
  548. startString = self.bates.startString;
  549. }
  550. NSString * newPage = @"";
  551. if (self.bates) {
  552. NSArray <NSTextCheckingResult *>* dates = [self match:@"<<#\\d*?#\\d*#.*?>>|<<#\\d*?#\\d*?>>" stri:oldString];
  553. for (NSTextCheckingResult *object in dates) {
  554. NSRange range = object.range;
  555. NSString *resultStr = [oldString substringWithRange:range]?:@"";
  556. NSString *newResultStr = [resultStr substringWithRange:NSMakeRange(2, resultStr.length - 4)];
  557. NSArray *array = [newResultStr componentsSeparatedByString:@"#"];
  558. if (array.count >1) {
  559. NSString *batesDigits = array[1];
  560. if (array.count > 2) {
  561. NSString *firstString = array[2];
  562. newPage = [NSString stringWithFormat:@"%0*ld",batesDigits.integerValue,page + firstString.integerValue];
  563. }
  564. if(array.count > 3) {
  565. newPage = [NSString stringWithFormat:@"%@%@",array[3],newPage];
  566. }
  567. if(array.count > 4) {
  568. newPage = [newPage stringByAppendingString:array[4]];
  569. }
  570. newString = [newString stringByReplacingOccurrencesOfString:resultStr withString:newPage];
  571. }
  572. }
  573. } else {
  574. newPage = [NSString stringWithFormat:@"%ld",page + startString.integerValue];
  575. if (startString) {
  576. newString = convertViewPageFormat(newString, newPage, [NSString stringWithFormat:@"%ld",self.document.pageCount + startString.integerValue - 1]);
  577. }
  578. }
  579. newString = convertDateFormat(newString);
  580. return newString;
  581. }
  582. - (NSArray <NSTextCheckingResult *>*)match:(NSString *)pattern stri:(NSString *)testString{
  583. // 1.创建正则表达式
  584. NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:pattern options:0 error:nil];
  585. // 2.测试字符串
  586. NSArray <NSTextCheckingResult *>* results = [regex matchesInString:testString options:0 range:NSMakeRange(0, testString.length)];
  587. return results;
  588. }
  589. static NSString * convertDateFormat (NSString *oldString) {
  590. NSString *newString = oldString;
  591. for (NSString *dateFormat in KMWatermarkAdjectiveTools.getDateFormats) {
  592. if ([newString containsString:dateFormat]) {
  593. NSString * formatString = [dateFormat stringByReplacingOccurrencesOfString:@"m" withString:@"M"];
  594. NSString *replace = [NSString stringWithFormat:@"<<%@>>",dateFormat];
  595. NSDate *date=[NSDate date];
  596. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
  597. dateFormatter.dateFormat = formatString;
  598. NSString * dateString = [dateFormatter stringFromDate:date];
  599. newString= [newString stringByReplacingOccurrencesOfString:replace withString:dateString];
  600. }
  601. }
  602. return newString;
  603. }
  604. static NSString * convertViewPageFormat (NSString *oldString,NSString * currentPage,NSString * pageCount) {
  605. NSString *newString = oldString;
  606. NSArray *PageFromatArray = @[@"1",
  607. @"1 of n",
  608. @"1/n",
  609. @"Page 1",
  610. @"Page 1 of n"];
  611. for (NSString *format in PageFromatArray) {
  612. NSString *pageFormat = [NSString stringWithFormat:@"<<%@>>",format];
  613. if ([newString containsString:pageFormat]) {
  614. NSString *tString = nil;
  615. if ([pageFormat isEqual:@"<<1>>"]) {
  616. tString = currentPage;
  617. } else if ([pageFormat isEqual:@"<<1 of n>>"]) {
  618. tString = [NSString stringWithFormat:@"%@ of %@",currentPage,pageCount];
  619. } else if ([pageFormat isEqual:@"<<1/n>>"]){
  620. tString = [NSString stringWithFormat:@"%@/%@",currentPage,pageCount];
  621. } else if ([pageFormat isEqual:@"<<Page 1>>"]){
  622. tString = [NSString stringWithFormat:@"Page %@",currentPage];
  623. } else if ([pageFormat isEqual:@"<<Page 1 of n>>"]){
  624. tString = [NSString stringWithFormat:@"Page %@ of %@",currentPage,pageCount];
  625. }
  626. newString= [newString stringByReplacingOccurrencesOfString:pageFormat withString:tString];
  627. }
  628. }
  629. return newString;
  630. }
  631. @end