// // KMPageEditTools.swift // PDF Reader Pro // // Created by tangchao on 2023/1/11. // import Cocoa enum KMPageSizeUint: String { case mm = "mm" case cm = "cm" case km_in = "in" } class KMPageEditTools: NSObject { class func insert(_ document: CPDFDocument, _ index: Int, _ pages: Array) -> Bool { // for i in 0 ..< pages.count { // document.insertPageObject(pages[i], at: UInt(index+i)) // } document.insertPageObject(pages.first, at: 0) return true } class func showInsertMenu(callback: (_ index: Int) -> ()) { } class func extract(_ document: CPDFDocument, _ pageIndexs: IndexSet,_ oneDocument: Bool,_ window: NSWindow, callback: @escaping (_ result: Bool, _ urls: Array?, _ error: String) -> ()) { /// 提取的页面 var extractPages: Array = [] for i in pageIndexs { extractPages.append(document.page(at: UInt(i))) } if (oneDocument) { /// 提取为一个文档 var fileName = document.documentURL.deletingPathExtension().lastPathComponent fileName.append(" pages ") fileName.append(KMPageRangeTools.newParseSelectedIndexs(selectedIndex: pageIndexs.sorted())) fileName.append(".pdf") NSPanel.savePanel(window, true) { panel in panel.nameFieldStringValue = fileName } completion: { response, url, isOpen in if (response != .OK) { callback(false, nil, "cancel") return } DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { let saveFilePath = url!.path DispatchQueue.global().async { var pdf = CPDFDocument.init() let success = pdf?.extractAsOneDocument(withPages: extractPages, savePath: saveFilePath) ?? false DispatchQueue.main.async { if (success == false) { callback(false, nil, "failure") return } if (isOpen == false) { let url = URL(fileURLWithPath: saveFilePath) NSWorkspace.shared.activateFileViewerSelecting([url]) } else { NSDocumentController.shared.km_safe_openDocument(withContentsOf: URL(fileURLWithPath: saveFilePath), display: true) { _, _, _ in } } callback(true, [URL(fileURLWithPath: saveFilePath)], "") } } } } return } let panel = NSOpenPanel() panel.canChooseFiles = false panel.canChooseDirectories = true panel.canCreateDirectories = true panel.allowsMultipleSelection = false panel.beginSheetModal(for: window) { response in if response != .OK { callback(false, nil, "cancel") return } DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { let outputURL = panel.url DispatchQueue.global().async { let folderName = String(((document.documentURL?.lastPathComponent.split(separator: ".").first) ?? "")) + "_extract" var filePath = URL(fileURLWithPath: outputURL?.path ?? "").appendingPathComponent(folderName).path var i = 1 let testFilePath = filePath while FileManager.default.fileExists(atPath: filePath) { filePath = testFilePath + "\(i)" i += 1 } try? FileManager.default.createDirectory(atPath: filePath, withIntermediateDirectories: false, attributes: nil) let successArray = document.extractPerPageDocument(withPages: extractPages, folerPath: filePath) ?? [] DispatchQueue.main.async { if successArray.count == 0 { callback(false, nil, "failure") return } NSWorkspace.shared.activateFileViewerSelecting(successArray) callback(true, successArray, "") } } } } } class func split(_ document: CPDFDocument, _ avgNumberPage: Int, _ path: String, _ filename: String, callback: @escaping (_ result: Bool, _ outputDocuments: Array?, _ error: String) -> ()) { if (avgNumberPage == 0) { callback(false, nil, "avgNumberPage = 0.") return } var fileCount: Int = (Int(document.pageCount) / avgNumberPage) + 1 var files: Array = [] for i in 0 ..< fileCount { var indexs: IndexSet = [] for j in 0 ..< avgNumberPage { if (i * avgNumberPage + j >= document.pageCount) { break } indexs.insert(i * avgNumberPage + j) } files.append(indexs) } var array: Array = [] for indexs in files { let document_new: CPDFDocument = CPDFDocument() document_new.importPages(indexs, from: document, at: 0) array.append(document_new) // document_new.write(to: <#T##URL!#>) } callback(true, array, "") } class func split(_ document: CPDFDocument, _ model: KMPageEditSplitSettingModel, _ path: String, _ filename: String, callback: @escaping (_ result: Bool, _ outputFilepaths: Array?, _ error: String) -> ()) { let file_indexs = model.getSplitIndexSets ?? [] if (file_indexs.count <= 0) { callback(false, nil, "") return } let filePath = "\(path)/\(document.documentURL.deletingPathExtension().lastPathComponent)" if (!FileManager.default.fileExists(atPath: filePath)) { try?FileManager.default.createDirectory(atPath: filePath, withIntermediateDirectories: true) } var filepaths: [String] = [] for i in 0 ..< file_indexs.count { let indexs = file_indexs[i] let filepath = String(format: "%@/%@ %d.pdf", filePath, filename, i+1) filepaths.append(filepath) let newDocument = CPDFDocument() newDocument?.importPages(indexs, from: document, at: 0) newDocument?.write(to: URL(fileURLWithPath: filepath)) } callback(true, filepaths, "") } class func reverse(_ document: CPDFDocument, _ selectedIndexs: IndexSet, callback: @escaping (_ result: Bool, _ error: String) -> ()) { if (document.pageCount <= 0) { callback(false, "") return } if (selectedIndexs.count <= 1) { callback(false, "") return } var pages: Array = [] for i in 0 ..< document.pageCount { if (selectedIndexs.contains(IndexSet.Element(i))) { pages.append(document.page(at: i)) } } var first: Int = 0 var last: Int = pages.count-1 while (last > first) { let beforePage: CPDFPage = pages[first] let afterPage: CPDFPage = pages[last] let beforeIndex = document.index(for: beforePage) let afterIndex = document.index(for: afterPage) document.removePage(at: UInt(afterIndex)) document.removePage(at: UInt(beforeIndex)) document.insertPageObject(afterPage, at: UInt(beforeIndex)) document.insertPageObject(beforePage, at: UInt(afterIndex)) first += 1 last -= 1 } callback(true, "") } class func getPageSize() -> Array { return KMCropTools.getPageSize() } class func getPageSizeValue(_ pageSize: String) -> NSSize { return KMCropTools.getPageSizeValue(pageSize) } class func getAllPageSizeUnit() -> Array { return [KMPageSizeUint.mm.rawValue, KMPageSizeUint.cm.rawValue,KMPageSizeUint.km_in.rawValue] } class func convertSize(with fromUnit: KMPageSizeUint, to toUnit: KMPageSizeUint, value: CGFloat) -> String { var result: CGFloat = value if (fromUnit == toUnit) { } else if (toUnit == .cm) { if (fromUnit == .mm) { result = value / 10.0 } else if (fromUnit == .km_in) { result = value * 25.4 } } else if (toUnit == .mm) { if (fromUnit == .cm) { result = value * 10 } else if (fromUnit == .km_in) { result = value * 10 * 25.4 } } else if (toUnit == .km_in) { if (fromUnit == .cm) { result = value / 25.4 } else if (fromUnit == .mm) { result = value/10.0/25.4 } } if (fmodf(Float(result), 1) == 0) { /// 如果有一位小数点 return String(format: "%.0f", result) } else if (fmodf(Float(result*10), 1) == 0) { //如果有两位小数点 return String(format: "%.1f", result) } else { return String(format: "%.2f", result) } } class func sizeUnitToBoundSize(unit: KMPageSizeUint, pageSize: NSSize) -> NSSize { let fromUnit = unit let toUnit: KMPageSizeUint = .mm var result: NSSize = pageSize if (fromUnit == .cm) { result = NSSize(width: pageSize.width * 10, height: pageSize.height * 10) } else if (fromUnit == .km_in) { result = NSSize(width: pageSize.width * 10 * 25.4,height: pageSize.height * 10 * 25.4) } let width = result.width let height = result.height return NSSize(width: width * 595 / 210, height: height * 842 / 297) } class func boundSizeToUnitSize(size boundSize: NSSize, to toUnit: KMPageSizeUint) -> NSSize { let _fromUnit = toUnit let _toUnit: KMPageSizeUint = .mm var result: NSSize = boundSize if (_fromUnit == .cm) { result = NSSize(width: boundSize.width * 10, height: boundSize.height * 10) } else if (_fromUnit == .km_in) { result = NSSize(width: boundSize.width * 10 * 25.4,height: boundSize.height * 10 * 25.4) } let width = result.width let height = result.height return NSSize(width: width * 210 / 595, height: height * 297 / 842) } }