KMOCTool.m 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. //
  2. // KMOCTool.m
  3. // PDF Reader Pro
  4. //
  5. // Created by liujiajie on 2023/11/15.
  6. //
  7. #import "KMOCTool.h"
  8. #import <Foundation/Foundation.h>
  9. #import <PDF_Reader_Pro-Swift.h>
  10. @implementation KMOCTool
  11. + (void)createPDFFile:(NSString *)filePath imagePaths:(NSArray *)paths results:(NSArray *)resultsArray scale:(CGFloat)scale {
  12. if (paths.count < 1) {
  13. return;
  14. }
  15. CFStringRef path = (__bridge CFStringRef)filePath;
  16. CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, 0);
  17. CFMutableDictionaryRef myDictionary = CFDictionaryCreateMutable(NULL,
  18. 0,
  19. &kCFTypeDictionaryKeyCallBacks,
  20. &kCFTypeDictionaryValueCallBacks);
  21. CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR("Kdan Mobile PDF Reader"));
  22. CGContextRef pdfContext = CGPDFContextCreateWithURL(url, &CGRectZero, myDictionary);
  23. CGContextSetRGBFillColor(pdfContext, 1.0, 0.0, 0.0, 0.0);
  24. CGContextSetTextDrawingMode(pdfContext, kCGTextFill);
  25. CFRelease(myDictionary);
  26. CFRelease(url);
  27. for (int i=0; i<paths.count; i++) {
  28. NSString *path = [paths objectAtIndex:i];
  29. NSImage *image = [[NSImage alloc] initWithContentsOfFile:path];
  30. CIImage *imageCIImage = [CIImage imageWithContentsOfURL:[NSURL fileURLWithPath:path]];
  31. NSSize size = [imageCIImage extent].size;
  32. CGRect pageRect = CGRectMake(0, 0, size.width/scale, size.height/scale);
  33. CFMutableDictionaryRef pageDictionary = CFDictionaryCreateMutable(NULL,
  34. 0,
  35. &kCFTypeDictionaryKeyCallBacks,
  36. &kCFTypeDictionaryValueCallBacks);
  37. CFDataRef boxData = CFDataCreate(NULL,(const UInt8 *)&pageRect, sizeof (CGRect));
  38. CFDictionarySetValue(pageDictionary, kCGPDFContextMediaBox, boxData);
  39. CGPDFContextBeginPage (pdfContext, pageDictionary);
  40. NSData *imageData = [NSData dataWithContentsOfFile:path];
  41. CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL);
  42. CGImageRef imageRef = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);
  43. CGContextSaveGState(pdfContext);
  44. CGContextDrawImage(pdfContext, pageRect, imageRef);
  45. CGContextRestoreGState(pdfContext);
  46. CGImageRelease(imageRef);
  47. [NSGraphicsContext saveGraphicsState];
  48. [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithCGContext:pdfContext flipped:NO]];
  49. NSArray *results = nil;
  50. if (i < resultsArray.count) {
  51. results = resultsArray[i];
  52. CGFloat newScale = scale;
  53. if([KMGOCRManager defaultManager].OCRType == KMOCRType_Apple)
  54. newScale = 1;
  55. if (results.count == 1) {
  56. KMGOCRResult *result = results[0];
  57. NSRect bounds = NSMakeRect((result.textBounds.origin.x)/newScale,
  58. pageRect.size.height-(result.textBounds.origin.y+result.textBounds.size.height)/newScale,
  59. (result.textBounds.size.width)/newScale,
  60. (result.textBounds.size.height)/newScale);
  61. NSDictionary *dic = @{NSFontAttributeName:FontWithSize(result.text, CGSizeMake(result.textBounds.size.width/newScale, result.textBounds.size.height/newScale)),
  62. NSForegroundColorAttributeName:[NSColor clearColor]};
  63. [result.text drawInRect:bounds withAttributes:dic];
  64. } else {
  65. for (int i=1; i<results.count; i++) {
  66. KMGOCRResult *result = results[i];
  67. NSRect bounds = NSMakeRect((result.textBounds.origin.x)/newScale,
  68. pageRect.size.height-(result.textBounds.origin.y+result.textBounds.size.height)/newScale,
  69. (result.textBounds.size.width)/newScale,
  70. (result.textBounds.size.height)/newScale);
  71. NSDictionary *dic = @{NSFontAttributeName:FontWithSize(result.text, CGSizeMake(result.textBounds.size.width/newScale, result.textBounds.size.height/newScale)),
  72. NSForegroundColorAttributeName:[NSColor clearColor]};
  73. [result.text drawInRect:bounds withAttributes:dic];
  74. }
  75. }
  76. }
  77. [NSGraphicsContext restoreGraphicsState];
  78. CGPDFContextEndPage (pdfContext);
  79. CFRelease(pageDictionary);
  80. CFRelease(boxData);
  81. image = nil;
  82. }
  83. CGPDFContextClose(pdfContext);
  84. CGContextRelease (pdfContext);
  85. }
  86. + (CGRect)localCropRectForWindow:(CGWindowID)wNumber withBounds:(CGRect)bounds{
  87. CFArrayRef tarray = CGWindowListCreate(kCGWindowListOptionOnScreenOnly,
  88. (CGWindowID)wNumber);
  89. CFArrayRef array = CGWindowListCreateDescriptionFromArray(tarray);
  90. CFRelease(tarray);
  91. CGRect cropRect = bounds;
  92. for (NSDictionary *windowInfo in CFBridgingRelease(array)) {
  93. if ([windowInfo[(__bridge NSString*)kCGWindowNumber] integerValue] == wNumber) {
  94. NSDictionary *rectInfo = windowInfo[(__bridge NSString*)kCGWindowBounds];
  95. NSScreen *mainScreen = nil;
  96. for (NSScreen *screen in [NSScreen screens]) {
  97. if (CGPointEqualToPoint(screen.frame.origin, CGPointZero))
  98. mainScreen = screen;
  99. }
  100. CGPoint center = CGPointMake([rectInfo[@"X"] floatValue] + [rectInfo[@"Width"] floatValue]/2,
  101. mainScreen.frame.size.height - [rectInfo[@"Y"] floatValue] - [rectInfo[@"Height"] floatValue]/2);
  102. NSScreen *curScreen = nil;
  103. for (NSScreen *screen in [NSScreen screens]) {
  104. if (CGRectContainsPoint(screen.frame, center)) {
  105. curScreen = screen;
  106. break;
  107. }
  108. }
  109. if (!curScreen) {
  110. center = CGPointMake([rectInfo[@"X"] floatValue],
  111. mainScreen.frame.size.height - [rectInfo[@"Y"] floatValue]);
  112. for (NSScreen *screen in [NSScreen screens]) {
  113. if (CGRectContainsPoint(screen.frame, center)) {
  114. curScreen = screen;
  115. break;
  116. }
  117. }
  118. if (!curScreen) {
  119. center = CGPointMake([rectInfo[@"X"] floatValue] + [rectInfo[@"Width"] floatValue],
  120. mainScreen.frame.size.height - [rectInfo[@"Y"] floatValue]);
  121. for (NSScreen *screen in [NSScreen screens]) {
  122. if (CGRectContainsPoint(screen.frame, center)) {
  123. curScreen = screen;
  124. break;
  125. }
  126. }
  127. }
  128. }
  129. if (curScreen) {
  130. float y = mainScreen.frame.size.height - [rectInfo[@"Y"] floatValue] - curScreen.frame.origin.y;
  131. cropRect = CGRectMake([rectInfo[@"X"] floatValue] - curScreen.frame.origin.x,
  132. y - [rectInfo[@"Height"] floatValue],
  133. [rectInfo[@"Width"] floatValue],
  134. [rectInfo[@"Height"] floatValue]);
  135. }else {
  136. }
  137. break;
  138. }
  139. }
  140. return cropRect;
  141. }
  142. +(NSAttributedString *)transformAttr:(NSAttributedString *)astring withString:(NSString *)str{
  143. NSUInteger i, l = [str length];
  144. NSRange r = NSMakeRange(0, l);
  145. while (NSNotFound != (i = NSMaxRange([str rangeOfCharacterFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet] options:NSAnchoredSearch range:r])))
  146. r = NSMakeRange(i, l - i);
  147. while (NSNotFound != (i = [str rangeOfCharacterFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet] options:NSBackwardsSearch | NSAnchoredSearch range:r].location))
  148. r.length = i - r.location;
  149. if (r.length == 0)
  150. astring = nil;
  151. else if (NSMaxRange(r) < l)
  152. astring = [astring attributedSubstringFromRange:r];
  153. return astring;
  154. }
  155. + (id)nonWhitespaceAndNewlineCharacterSet {
  156. static NSCharacterSet *nonWhitespaceAndNewlineCharacterSet = nil;
  157. if (nonWhitespaceAndNewlineCharacterSet == nil)
  158. nonWhitespaceAndNewlineCharacterSet = [[[NSCharacterSet whitespaceAndNewlineCharacterSet] invertedSet] copy];
  159. return nonWhitespaceAndNewlineCharacterSet;
  160. }
  161. +(NSData*)convertStringsToPDFWithString:(NSArray *)strings{
  162. return convertStringsToPDF(strings);
  163. }
  164. static inline NSFont * FontWithSize(NSString *strChar, CGSize size) {
  165. CGFloat fontsize = 1.0;
  166. NSFont *font = [NSFont systemFontOfSize:fontsize];
  167. CGSize strSize = [strChar sizeWithAttributes:@{NSFontAttributeName:font}];
  168. while ((fontsize<127) && (strSize.width<size.width || strSize.height<size.height)) {
  169. fontsize += 1.0;
  170. font = [NSFont systemFontOfSize:fontsize];
  171. strSize = [strChar sizeWithAttributes:@{NSFontAttributeName:font}];
  172. }
  173. return [NSFont systemFontOfSize:fontsize-1];
  174. }
  175. static NSData *convertStringsToPDF(NSArray<NSAttributedString *> *strings)
  176. {
  177. NSMutableData *pdfData = [[NSMutableData alloc] init];
  178. CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData((CFMutableDataRef)pdfData);
  179. CFMutableDictionaryRef myDictionary = CFDictionaryCreateMutable(NULL,
  180. 0,
  181. &kCFTypeDictionaryKeyCallBacks,
  182. &kCFTypeDictionaryValueCallBacks);
  183. CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR("PDF Reader Pro"));
  184. CGRect mediaBox = CGRectMake(0, 0, 595, 842);
  185. CGContextRef pdfContext = CGPDFContextCreate(consumer, &mediaBox, myDictionary);
  186. CGContextSetRGBFillColor(pdfContext, 1.0, 0.0, 0.0, 0.0);
  187. CGContextSetTextDrawingMode(pdfContext, kCGTextFill);
  188. CFRelease(myDictionary);
  189. for (NSAttributedString *attributeString in strings) {
  190. if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_10) {
  191. NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributeString];
  192. NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
  193. [textStorage addLayoutManager:layoutManager];
  194. while (YES) {
  195. NSSize contentSize = NSMakeSize(mediaBox.size.width-40,
  196. mediaBox.size.height-40);
  197. NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:contentSize];
  198. [layoutManager addTextContainer:textContainer];
  199. NSRange rang = [layoutManager glyphRangeForTextContainer:textContainer];
  200. if (rang.length <= 0 ||
  201. rang.length + rang.location > attributeString.length) {
  202. break;
  203. }
  204. NSAttributedString *attStr = [attributeString attributedSubstringFromRange:rang];
  205. [NSGraphicsContext saveGraphicsState];
  206. // [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:pdfContext flipped:NO]];
  207. [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithCGContext:pdfContext flipped:NO]];
  208. CGContextBeginPage(pdfContext, &mediaBox);
  209. [attStr drawInRect:CGRectMake(20, 20,
  210. mediaBox.size.width-40,
  211. mediaBox.size.height-40)];
  212. CGContextEndPage(pdfContext);
  213. [NSGraphicsContext restoreGraphicsState];
  214. }
  215. } else {
  216. [NSGraphicsContext saveGraphicsState];
  217. [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithCGContext:pdfContext flipped:NO]];
  218. CGContextBeginPage(pdfContext, &mediaBox);
  219. [attributeString drawInRect:CGRectMake(20, 20,
  220. mediaBox.size.width-40,
  221. mediaBox.size.height-40)];
  222. CGContextEndPage(pdfContext);
  223. [NSGraphicsContext restoreGraphicsState];
  224. }
  225. }
  226. CGPDFContextClose(pdfContext);
  227. CGContextRelease (pdfContext);
  228. return pdfData;
  229. }
  230. + (NSDictionary *)convertExcelToPdfFilePath:(NSString *)filePath savePath:(NSString *)savePath{
  231. NSString * convertString = [NSString stringWithFormat:@"set filePath to\"%@\"\n",filePath];
  232. convertString = [convertString stringByAppendingFormat:@"set savePath to \"%@\"\n",savePath];
  233. convertString = [convertString stringByAppendingFormat:@"set tFile to (POSIX path of filePath) as POSIX file\n"];
  234. convertString = [convertString stringByAppendingFormat:@"tell application \"Microsoft Excel\"\n"];
  235. convertString = [convertString stringByAppendingFormat:@"set isRun to running\n"];
  236. convertString = [convertString stringByAppendingFormat:@"set wkbk1 to open workbook workbook file name tFile\n"];
  237. convertString = [convertString stringByAppendingFormat:@"alias savePath\n"];
  238. convertString = [convertString stringByAppendingFormat:@"save workbook as wkbk1 filename savePath file format PDF file format with overwrite\n"];
  239. convertString = [convertString stringByAppendingFormat:@"close wkbk1 saving no\n"];
  240. convertString = [convertString stringByAppendingFormat:@"if not isRun then quit\n"];
  241. convertString = [convertString stringByAppendingFormat:@"end tell\n"];
  242. NSDictionary * dic = nil;
  243. NSAppleScript *docScript = [[NSAppleScript alloc] initWithSource:convertString];
  244. [docScript executeAndReturnError:&dic];
  245. return dic;
  246. }
  247. + (NSDictionary *)convertOfficeFileToPdf:(NSString *)convertString{
  248. NSDictionary * dic = nil;
  249. NSAppleScript *docScript = [[NSAppleScript alloc] initWithSource:convertString];
  250. [docScript executeAndReturnError:&dic];
  251. return dic;
  252. }
  253. @end