KMWatermarkPDFView_OC.m 36 KB

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