CPDFSampleView.m 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. //
  2. // CPDFSampleView.m
  3. // ComPDFKit_Tools
  4. //
  5. // Copyright © 2014-2024 PDF Technologies, Inc. All Rights Reserved.
  6. //
  7. // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
  8. // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
  9. // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
  10. // This notice may not be removed from this file.
  11. //
  12. #import "CPDFSampleView.h"
  13. #if __has_include(<ComPDFKit_Tools/ComPDFKit_Tools.h>)
  14. #import <ComPDFKit_Tools/ComPDFKit_Tools.h>
  15. #else
  16. #import "ComPDFKit_Tools.h"
  17. #endif
  18. #define PI 3.14159265358979323846
  19. @interface CPDFSampleView ()
  20. @property (nonatomic, assign) CGRect centerRect;
  21. @property (nonatomic, assign) CGRect arrowRect;
  22. @property (nonatomic, assign) CGRect textRect;
  23. @property (nonatomic, assign) CGRect inkRect;
  24. @end
  25. @implementation CPDFSampleView
  26. #pragma mark - Initializers
  27. - (instancetype)initWithFrame:(CGRect)frame {
  28. if (self = [super initWithFrame:frame]) {
  29. }
  30. return self;
  31. }
  32. - (void)layoutSubviews {
  33. [super layoutSubviews];
  34. [self setNeedsDisplay];
  35. }
  36. - (void)drawRect:(CGRect)rect {
  37. [super drawRect:rect];
  38. CGContextRef context = UIGraphicsGetCurrentContext();
  39. self.centerRect = CGRectInset(rect, (self.bounds.size.width/20)*9, (self.bounds.size.height/8)*3);
  40. CGPoint centerPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
  41. self.arrowRect = CGRectMake(centerPoint.x-self.bounds.size.height/4, centerPoint.y-self.bounds.size.height/4, self.bounds.size.height/2, self.bounds.size.height/2);
  42. self.textRect = CGRectInset(rect, self.bounds.size.width/3+3, self.bounds.size.height/3);
  43. self.inkRect = CGRectInset(rect, self.bounds.size.width/4, self.bounds.size.height/3);
  44. CGContextSetFillColorWithColor(context, [CPDFColorUtils CAnnotationSampleDrawBackgoundColor].CGColor);
  45. CGContextFillRect(context, self.bounds);
  46. [self drawSamples:context rect:self.centerRect];
  47. }
  48. #pragma mark - Private Methods
  49. - (void)drawSamples:(CGContextRef)context rect:(CGRect)rect {
  50. switch (self.selecIndex) {
  51. case CPDFSamplesNote:
  52. {
  53. CGContextSetRGBStrokeColor(context, 0, 0, 0, 1.0);
  54. if(self.color) {
  55. CGFloat red, green, blue, alpha;
  56. [self.color getRed:&red green:&green blue:&blue alpha:&alpha];
  57. UIColor *color = [UIColor colorWithRed:red green:green blue:blue alpha:self.opcity];
  58. CGContextSetFillColorWithColor(context, color.CGColor);
  59. } else {
  60. CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
  61. CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
  62. }
  63. // Draw outer boxes.
  64. CGFloat width = 1.0;
  65. CGFloat size = rect.size.height / 5;
  66. CGRect outerRect1 = CGRectInset(rect, 0, 0);
  67. outerRect1.size.height -= size;
  68. CGRect outerRect2 = outerRect1;
  69. outerRect2.origin.x += size;
  70. outerRect2.origin.y += size*4;
  71. outerRect2.size.width = size;
  72. outerRect2.size.height = size;
  73. CGContextSetLineWidth(context, width);
  74. CGContextMoveToPoint(context, CGRectGetMinX(outerRect1), CGRectGetMinY(outerRect1));
  75. CGContextAddLineToPoint(context, CGRectGetMinX(outerRect1), CGRectGetMaxY(outerRect1));
  76. CGContextAddLineToPoint(context, CGRectGetMinX(outerRect2), CGRectGetMinY(outerRect2));
  77. CGContextAddLineToPoint(context, CGRectGetMidX(outerRect2), CGRectGetMaxY(outerRect2));
  78. CGContextAddLineToPoint(context, CGRectGetMidX(outerRect2), CGRectGetMinY(outerRect2));
  79. CGContextAddLineToPoint(context, CGRectGetMaxX(outerRect1), CGRectGetMaxY(outerRect1));
  80. CGContextAddLineToPoint(context, CGRectGetMaxX(outerRect1), CGRectGetMinY(outerRect1));
  81. CGContextClosePath(context);
  82. CGContextDrawPath(context, kCGPathFillStroke);
  83. // Draw inner lines.
  84. int count = 3;
  85. CGFloat xDelta = rect.size.width / 10;
  86. CGFloat yDelta = outerRect1.size.height / (count + 1);
  87. CGRect lineRect = outerRect1;
  88. lineRect.origin.x += xDelta;
  89. lineRect.size.width -= 2*xDelta;
  90. for (int i=0; i<count; i++) {
  91. CGFloat y = CGRectGetMaxY(lineRect) - yDelta * (i + 1);
  92. CGContextMoveToPoint(context, CGRectGetMinX(lineRect), y);
  93. CGContextAddLineToPoint(context, CGRectGetMaxX(lineRect), y);
  94. CGContextStrokePath(context);
  95. }
  96. }
  97. break;
  98. case CPDFSamplesHighlight:
  99. {
  100. CGFloat red, green, blue, alpha;
  101. [self.color getRed:&red green:&green blue:&blue alpha:&alpha];
  102. CGContextSetFillColorWithColor(context, [UIColor colorWithRed:red green:green blue:blue alpha:self.opcity].CGColor);
  103. CGContextFillRect(context, self.textRect);
  104. NSString *sampleStr = @"Sample";
  105. UIFont *font = [UIFont systemFontOfSize:27];
  106. NSDictionary *dic = @{NSFontAttributeName:font, NSForegroundColorAttributeName:[UIColor blackColor]};
  107. [sampleStr drawInRect:self.textRect withAttributes:dic];
  108. }
  109. break;
  110. case CPDFSamplesUnderline:
  111. {
  112. NSString *sampleStr = @"Sample";
  113. CGFloat red, green, blue, alpha;
  114. [self.color getRed:&red green:&green blue:&blue alpha:&alpha];
  115. CGContextSetFillColorWithColor(context, [UIColor colorWithRed:red green:green blue:blue alpha:self.opcity].CGColor);
  116. CGRect strikeoutRect = CGRectInset(self.textRect, 0, (self.textRect.size.height/7)*3);
  117. CGRect underLineRect = CGRectOffset(strikeoutRect, 0, (self.textRect.size.height/7)*3);
  118. CGContextFillRect(context, underLineRect);
  119. UIFont *font = [UIFont systemFontOfSize:27];
  120. NSDictionary *dic = @{NSFontAttributeName:font, NSForegroundColorAttributeName:[UIColor blackColor]};
  121. [sampleStr drawInRect:self.textRect withAttributes:dic];
  122. }
  123. break;
  124. case CPDFSamplesStrikeout:
  125. {
  126. NSString *sampleStr = @"Sample";
  127. CGFloat red, green, blue, alpha;
  128. [self.color getRed:&red green:&green blue:&blue alpha:&alpha];
  129. CGContextSetFillColorWithColor(context, [UIColor colorWithRed:red green:green blue:blue alpha:self.opcity].CGColor);
  130. CGRect strikeoutRect = CGRectInset(self.textRect, 0, (self.textRect.size.height/7)*3);
  131. CGRect underLineRect = CGRectOffset(strikeoutRect, 0, (self.textRect.size.height/7));
  132. CGContextFillRect(context, underLineRect);
  133. UIFont *font = [UIFont systemFontOfSize:27];
  134. NSDictionary *dic = @{NSFontAttributeName:font, NSForegroundColorAttributeName:[UIColor blackColor]};
  135. [sampleStr drawInRect:self.textRect withAttributes:dic];
  136. }
  137. break;
  138. case CPDFSamplesSquiggly:
  139. {
  140. NSString *sampleStr = @"Sample";
  141. CGFloat red, green, blue, alpha;
  142. [self.color getRed:&red green:&green blue:&blue alpha:&alpha];
  143. CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:red green:green blue:blue alpha:self.opcity].CGColor);
  144. float tWidth = self.textRect.size.width / 12.0;
  145. CGContextMoveToPoint(context, CGRectGetMinX(self.textRect), CGRectGetMaxY(self.textRect));
  146. CGContextSetLineWidth(context, 2.0);
  147. CGContextAddCurveToPoint(context,
  148. CGRectGetMinX(self.textRect)+tWidth,CGRectGetMaxY(self.textRect)+5,
  149. CGRectGetMinX(self.textRect)+tWidth*2.0,CGRectGetMaxY(self.textRect)-5,
  150. CGRectGetMinX(self.textRect)+tWidth*3.0,CGRectGetMaxY(self.textRect));
  151. CGContextAddCurveToPoint(context,
  152. CGRectGetMinX(self.textRect)+tWidth*4.0,CGRectGetMaxY(self.textRect)+5,
  153. CGRectGetMinX(self.textRect)+tWidth*5.0,CGRectGetMaxY(self.textRect)-5,
  154. CGRectGetMinX(self.textRect)+tWidth*6.0,CGRectGetMaxY(self.textRect));
  155. CGContextAddCurveToPoint(context,
  156. CGRectGetMinX(self.textRect)+tWidth*7.0,CGRectGetMaxY(self.textRect)+5,
  157. CGRectGetMinX(self.textRect)+tWidth*8.0,CGRectGetMaxY(self.textRect)-5,
  158. CGRectGetMinX(self.textRect)+tWidth*9.0,CGRectGetMaxY(self.textRect));
  159. CGContextAddCurveToPoint(context,
  160. CGRectGetMinX(self.textRect)+tWidth*10.0,CGRectGetMaxY(self.textRect)+5,
  161. CGRectGetMinX(self.textRect)+tWidth*11.0,CGRectGetMaxY(self.textRect)-5,
  162. CGRectGetMinX(self.textRect)+tWidth*12.0,CGRectGetMaxY(self.textRect));
  163. CGContextStrokePath(context);
  164. UIFont *font = [UIFont systemFontOfSize:27];
  165. NSDictionary *dic = @{NSFontAttributeName:font, NSForegroundColorAttributeName:[UIColor blackColor]};
  166. [sampleStr drawInRect:self.textRect withAttributes:dic];
  167. }
  168. break;
  169. case CPDFSamplesFreehand:
  170. {
  171. CGFloat red, green, blue, alpha;
  172. [self.color getRed:&red green:&green blue:&blue alpha:&alpha];
  173. CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:red green:green blue:blue alpha:self.opcity].CGColor);
  174. float tWidth = self.inkRect.size.width / 3.0;
  175. CGContextMoveToPoint(context, CGRectGetMinX(self.inkRect), CGRectGetMidY(self.inkRect));
  176. CGContextSetLineWidth(context, self.thickness);
  177. CGContextAddCurveToPoint(context,
  178. CGRectGetMinX(self.inkRect)+tWidth,CGRectGetMidY(self.inkRect)-20,
  179. CGRectGetMinX(self.inkRect)+tWidth*2.0,CGRectGetMidY(self.inkRect)+20,
  180. CGRectGetMinX(self.inkRect)+tWidth*3.0,CGRectGetMidY(self.inkRect));
  181. CGContextStrokePath(context);
  182. }
  183. break;
  184. case CPDFSamplesShapeCircle:
  185. {
  186. CGFloat red, green, blue, alpha;
  187. [self.color getRed:&red green:&green blue:&blue alpha:&alpha];
  188. CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:red green:green blue:blue alpha:self.opcity].CGColor);
  189. if (!([self.interiorColor isEqual:[UIColor clearColor]])) {
  190. CGFloat interRed, interGreen, interBlue, interAlpha;
  191. [self.interiorColor getRed:&interRed green:&interGreen blue:&interBlue alpha:&interAlpha];
  192. CGContextSetFillColorWithColor(context, [UIColor colorWithRed:interRed green:interGreen blue:interBlue alpha:self.opcity].CGColor);
  193. } else {
  194. CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
  195. }
  196. CGFloat dashLengths[2] = {6, self.dotted};
  197. CGContextSetLineDash(context, 0, dashLengths, 2);
  198. CGContextSetLineWidth(context, self.thickness);
  199. CGContextAddArc(context, CGRectGetMaxX(self.bounds)/2, CGRectGetMaxY(self.bounds)/2, 30, 0, 2*PI, 0);
  200. CGContextDrawPath(context, kCGPathStroke);
  201. CGContextAddArc(context, CGRectGetMaxX(self.bounds)/2, CGRectGetMaxY(self.bounds)/2, 30, 0, 2*PI, 0);
  202. CGContextDrawPath(context, kCGPathFill);
  203. }
  204. break;
  205. case CPDFSamplesShapeSquare:
  206. {
  207. CGFloat red, green, blue, alpha;
  208. [self.color getRed:&red green:&green blue:&blue alpha:&alpha];
  209. CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:red green:green blue:blue alpha:self.opcity].CGColor);
  210. if (!([self.interiorColor isEqual:[UIColor clearColor]])) {
  211. CGFloat interRed, interGreen, interBlue, interAlpha;
  212. [self.interiorColor getRed:&interRed green:&interGreen blue:&interBlue alpha:&interAlpha];
  213. CGContextSetFillColorWithColor(context, [UIColor colorWithRed:interRed green:interGreen blue:interBlue alpha:self.opcity].CGColor);
  214. } else {
  215. CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
  216. }
  217. CGContextSetLineWidth(context, self.thickness);
  218. CGFloat dashLengths[2] = {6, self.dotted};
  219. CGContextSetLineDash(context, 0, dashLengths, 2);
  220. CGContextMoveToPoint(context, CGRectGetMinX(self.centerRect), CGRectGetMinY(self.centerRect));
  221. CGContextAddLineToPoint(context, CGRectGetMaxX(self.centerRect)+0.1, CGRectGetMinY(self.centerRect));
  222. CGContextAddLineToPoint(context, CGRectGetMaxX(self.centerRect), CGRectGetMaxY(self.centerRect));
  223. CGContextAddLineToPoint(context, CGRectGetMinX(self.centerRect), CGRectGetMaxY(self.centerRect));
  224. CGContextAddLineToPoint(context, CGRectGetMinX(self.centerRect), CGRectGetMinY(self.centerRect));
  225. CGContextAddLineToPoint(context, CGRectGetMinX(self.centerRect)+0.1, CGRectGetMinY(self.centerRect));
  226. CGContextStrokePath(context);
  227. CGContextFillRect(context, rect);
  228. }
  229. break;
  230. case CPDFSamplesShapeArrow ... CPDFSamplesShapeLine:
  231. {
  232. CGFloat red, green, blue, alpha;
  233. [self.color getRed:&red green:&green blue:&blue alpha:&alpha];
  234. CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:red green:green blue:blue alpha:self.opcity].CGColor);
  235. CGContextSetLineWidth(context, self.thickness);
  236. CGPoint start = CGPointMake(CGRectGetMinX(self.arrowRect), CGRectGetMaxY(self.arrowRect));
  237. CGPoint end = CGPointMake(CGRectGetMaxX(self.arrowRect), CGRectGetMinY(self.arrowRect));
  238. [self drawEndArrow:context startPoint:start endPoint:end];
  239. [self drawStartArrow:context startPoint:start endPoint:end];
  240. CGFloat dashLengths[2] = {6, self.dotted};
  241. CGContextSetLineDash(context, 0, dashLengths, 2);
  242. CGContextMoveToPoint(context, start.x, start.y);
  243. CGContextAddLineToPoint(context, end.x, end.y);
  244. CGContextStrokePath(context);
  245. }
  246. break;
  247. case CPDFSamplesFreeText:
  248. {
  249. CGFloat red, green, blue, alpha;
  250. [self.color getRed:&red green:&green blue:&blue alpha:&alpha];
  251. NSString *sampleStr = @"Sample";
  252. UIFont *font = [UIFont fontWithName:self.fontName size:self.thickness];
  253. if (!self.color) {
  254. self.color = [UIColor whiteColor];
  255. }
  256. NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:sampleStr attributes:@{NSFontAttributeName:font, NSForegroundColorAttributeName:[UIColor colorWithRed:red green:green blue:blue alpha:self.opcity]}];
  257. CGSize textSize = [attributedText boundingRectWithSize:self.bounds.size options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) context:nil].size;
  258. CGFloat x = 0;
  259. CGFloat y = 0;
  260. switch (self.textAlignment) {
  261. case NSTextAlignmentLeft:
  262. {
  263. x = self.bounds.origin.x;
  264. y = self.bounds.origin.y + (self.bounds.size.height - textSize.height) / 2.0;
  265. }
  266. break;
  267. case NSTextAlignmentCenter:
  268. {
  269. x = self.bounds.origin.x + (self.bounds.size.width - textSize.width) / 2.0;
  270. y = self.bounds.origin.y + (self.bounds.size.height - textSize.height) / 2.0;
  271. }
  272. break;
  273. case NSTextAlignmentRight:
  274. {
  275. x = (self.bounds.size.width - textSize.width);
  276. y = self.bounds.origin.y + (self.bounds.size.height - textSize.height) / 2.0;
  277. }
  278. break;
  279. default:
  280. {
  281. x = self.bounds.origin.x + (self.bounds.size.width - textSize.width) / 2.0;
  282. y = self.bounds.origin.y + (self.bounds.size.height - textSize.height) / 2.0;
  283. }
  284. break;
  285. }
  286. CGPoint center = CGPointMake(x, y);
  287. [attributedText drawAtPoint:center];
  288. }
  289. break;
  290. default:
  291. break;
  292. }
  293. }
  294. - (void)drawStartArrow:(CGContextRef)context startPoint:(CGPoint)start endPoint:(CGPoint)end {
  295. switch (self.startArrowStyleIndex) {
  296. case CPDFArrowStyleOpenArrow:
  297. {
  298. CGContextMoveToPoint(context, start.x+10, start.y);
  299. CGContextAddLineToPoint(context, start.x, start.y);
  300. CGContextAddLineToPoint(context, start.x, start.y-10);
  301. CGContextStrokePath(context);
  302. }
  303. break;
  304. case CPDFArrowStyleClosedArrow:
  305. {
  306. CGContextMoveToPoint(context, start.x-5, start.y-5);
  307. CGContextAddLineToPoint(context, start.x-5, start.y+5);
  308. CGContextAddLineToPoint(context, start.x+5, start.y+5);
  309. CGContextClosePath(context);
  310. CGContextStrokePath(context);
  311. }
  312. break;
  313. case CPDFArrowStyleSquare:
  314. {
  315. CGContextMoveToPoint(context, start.x-2.5, start.y-2.5);
  316. CGContextAddLineToPoint(context, start.x-7.5, start.y+2.5);
  317. CGContextAddLineToPoint(context, start.x-2.5, start.y+7.5);
  318. CGContextAddLineToPoint(context, start.x+2.5, start.y+2.5);
  319. CGContextClosePath(context);
  320. CGContextStrokePath(context);
  321. }
  322. break;
  323. case CPDFArrowStyleCircle:
  324. {
  325. CGContextAddArc(context, start.x-2.5, start.y+2.5, 5, 0, 2*3.14159265358979323846, 0);
  326. CGContextDrawPath(context, kCGPathStroke);
  327. }
  328. break;
  329. case CPDFArrowStyleDiamond:
  330. {
  331. CGContextMoveToPoint(context, start.x, start.y);
  332. CGContextAddLineToPoint(context, start.x-5, start.y);
  333. CGContextAddLineToPoint(context, start.x-5, start.y+5);
  334. CGContextAddLineToPoint(context, start.x, start.y+5);
  335. CGContextClosePath(context);
  336. CGContextStrokePath(context);
  337. }
  338. break;
  339. default:
  340. break;
  341. }
  342. }
  343. - (void)drawEndArrow:(CGContextRef)context startPoint:(CGPoint)start endPoint:(CGPoint)end {
  344. switch (self.endArrowStyleIndex) {
  345. case CPDFArrowStyleOpenArrow:
  346. {
  347. CGContextMoveToPoint(context, end.x-10, end.y);
  348. CGContextAddLineToPoint(context, end.x, end.y);
  349. CGContextAddLineToPoint(context, end.x, end.y+10);
  350. CGContextStrokePath(context);
  351. }
  352. break;
  353. case CPDFArrowStyleClosedArrow:
  354. {
  355. CGContextMoveToPoint(context, end.x-5, end.y-5);
  356. CGContextAddLineToPoint(context, end.x+5, end.y-5);
  357. CGContextAddLineToPoint(context, end.x+5, end.y+5);
  358. CGContextClosePath(context);
  359. CGContextStrokePath(context);
  360. }
  361. break;
  362. case CPDFArrowStyleSquare:
  363. {
  364. CGContextMoveToPoint(context, end.x-2.5, end.y-2.5);
  365. CGContextAddLineToPoint(context, end.x+2.5, end.y+2.5);
  366. CGContextAddLineToPoint(context, end.x+7.5, end.y-2.5);
  367. CGContextAddLineToPoint(context, end.x+2.5, end.y-7.5);
  368. CGContextClosePath(context);
  369. CGContextStrokePath(context);
  370. }
  371. break;
  372. case CPDFArrowStyleCircle:
  373. {
  374. CGContextAddArc(context, end.x+2.5, end.y-2.5, 5, 0, 2*3.14159265358979323846, 0);
  375. CGContextDrawPath(context, kCGPathStroke);
  376. }
  377. break;
  378. case CPDFArrowStyleDiamond:
  379. {
  380. CGContextMoveToPoint(context, end.x, end.y);
  381. CGContextAddLineToPoint(context, end.x+5, end.y);
  382. CGContextAddLineToPoint(context, end.x+5, end.y-5);
  383. CGContextAddLineToPoint(context, end.x, end.y-5);
  384. CGContextClosePath(context);
  385. CGContextStrokePath(context);
  386. }
  387. break;
  388. default:
  389. break;
  390. }
  391. }
  392. @end