Last active
November 10, 2020 21:33
-
-
Save mustafardestroyer/b58cfb73f680a903048308de76f40482 to your computer and use it in GitHub Desktop.
MyScript Recognition
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Combine | |
import os | |
func initIInkEngine() -> IINKEngine? { | |
// Check that the MyScript certificate is present | |
if myCertificate.length == 0 { | |
os_log(.error, "Could not locate MyScript certificate") | |
return nil | |
} | |
// Create the iink runtime environment | |
let data = Data(bytes: myCertificate.bytes, count: myCertificate.length) | |
guard let engine = IINKEngine(certificate: data) else { | |
os_log(.error, "Invalid MyScript certificate") | |
return nil | |
} | |
// Configure the iink runtime environment | |
let configurationPath = Bundle.main.bundlePath.appending("/recognition-assets/conf") | |
do { | |
try engine.configuration.setStringArray( | |
[configurationPath], forKey: "configuration-manager.search-path" | |
) // Tells the engine where to load the recognition assets from. | |
} catch { | |
os_log(.error, "MyScript error, please check your resources assets: %@", error.localizedDescription) | |
return nil | |
} | |
// Set the temporary directory | |
do { | |
try engine.configuration.setString(NSTemporaryDirectory(), forKey: "content-package.temp-folder") | |
} catch { | |
os_log(.error, "Failed to set temporary folder: %@", error.localizedDescription) | |
return nil | |
} | |
do { | |
// Recommended for off-screen usage | |
try engine.configuration.setBoolean(false, forKey: "text.guides.enable") | |
} catch { | |
os_log(.error, "Failed disable myscript guides: %@", error.localizedDescription) | |
return nil | |
} | |
return engine | |
} | |
func initEditor(engine: IINKEngine) -> IINKEditor? { | |
let renderer = try! engine.createRenderer( | |
withDpiX: AppConstants.NcodeDPI, | |
dpiY: AppConstants.NcodeDPI, | |
target: nil, | |
error: () | |
) | |
guard let editor = engine.createEditor(renderer) else { | |
return nil | |
} | |
let fontMetricsProvider = FontMetricsProvider() | |
editor.setFontMetricsProvider(fontMetricsProvider) | |
var error: NSError? | |
editor.setViewSize( | |
CGSize(width: IdeaPadSpec.NcodeWidth, height: IdeaPadSpec.NcodeHeight), | |
error: &error | |
) | |
if error != nil { | |
os_log(.error, "Failed to set view size: %@", error!.localizedDescription) | |
return nil | |
} | |
var package: IINKContentPackage | |
package = try! engine.createPackage("text_\(UUID().uuidString).iink") | |
let part = try! package.createPart("Text") | |
editor.setPart(part, error: &error) | |
if error != nil { | |
os_log(.error, "Could not set MyScript Part: %@", error!.localizedDescription) | |
return nil | |
} | |
return editor | |
} | |
protocol HandwritingRecognizer { | |
func pointerDown(xStart: Double, yStart: Double) | |
func pointerMove(xNew: Double, yNew: Double) | |
func pointerUp(xEnd: Double, yEnd: Double) | |
func generateText() -> Future<String, TranscriptionError> | |
} | |
class MyScriptHandwritingRecognizer: HandwritingRecognizer { | |
var editor: IINKEditor | |
var events = [IINKPointerEvent]() | |
init(editor: IINKEditor) { | |
self.editor = editor | |
} | |
func pointerDown(xStart: Double, yStart: Double) { | |
events.append( | |
IINKPointerEventMakeDown( | |
CGPoint(x: xStart, y: yStart), | |
-1, // at | |
1.0, // force | |
.pen, // type | |
-1 // pointerId | |
) | |
) | |
} | |
func pointerMove(xNew: Double, yNew: Double) { | |
events.append( | |
IINKPointerEventMakeMove( | |
CGPoint(x: xNew, y: yNew), | |
-1, // at | |
1.0, // force | |
.pen, // type | |
-1 // pointerId | |
) | |
) | |
} | |
func pointerUp(xEnd: Double, yEnd: Double) { | |
events.append( | |
IINKPointerEventMakeUp( | |
CGPoint(x: xEnd, y: yEnd), | |
-1, // at | |
1.0, // force | |
.pen, // type | |
-1 // pointerId | |
) | |
) | |
} | |
func generateText() -> Future<String, TranscriptionError> { | |
let eventsCount = self.events.count | |
return Future { promise in | |
let result = self.events.withUnsafeMutableBufferPointer { ( | |
eventsPtr: inout UnsafeMutableBufferPointer<IINKPointerEvent> | |
) in | |
return eventsPtr.baseAddress?.withMemoryRebound( | |
to: IINKPointerEvent.self, capacity: eventsCount, { ptr -> String in | |
do { | |
try self.editor.pointerEvents(ptr, count: eventsCount, doProcessGestures: false) | |
} catch { | |
return "Sorry, there was an error transcribing this page." | |
} | |
self.editor.waitForIdle() | |
let result = try! self.editor.export_(self.editor.rootBlock, mimeType: .text) | |
return result | |
}) | |
} | |
self.editor.clear() | |
self.events.removeAll() | |
promise(.success(result!)) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment