Public edition prepared 2026-09-12. Personal/account/contact details are visibly redacted where present. The original SHA256 identifies the captured unredacted full file, not this redacted extract. PUBLIC-SHA256SUMS.txt identifies downloadable public files. This material is not a signed declaration or proof of an Apple-received Build. # S12 On-device Vision OCR Project key: scan Original relative path: ScanlyPDF/Services/OCRService.swift Captured: 2026-09-12T18:57:15+08:00 Original full-file SHA256: 4466d6c697543b42c508f5baf27ba70a6c722b892e0826047c2519b32f9f10c3 Evidence level: local source excerpt Build correspondence: not yet established with an Apple-received binary. Line numbers refer to the captured original file. Gaps are explicitly marked. No source code was changed. ## Original lines 1 to 31 ```text 0001 import PDFKit 0002 import UIKit 0003 import Vision 0004 0005 actor OCRService { 0006 struct PageResult: Identifiable, Sendable { let id: Int; let text: String } 0007 struct LayoutPageResult: Identifiable, Sendable { let id: Int; let observations: [TextObservation] } 0008 struct TextObservation: Identifiable, Sendable { 0009 let id = UUID() 0010 let text: String 0011 /// Top-left normalized coordinates, matching the paper editor model. 0012 let rect: CGRect 0013 } 0014 0015 func recognize(image: UIImage, languages: [String] = ["zh-Hans", "zh-Hant", "en-US", "ja-JP", "ko-KR", "es-ES", "fr-FR", "de-DE"]) async throws -> String { 0016 guard let cgImage = image.cgImage else { throw AppError.invalidFile } 0017 return try await withCheckedThrowingContinuation { continuation in 0018 let request = VNRecognizeTextRequest { request, error in 0019 if let error { continuation.resume(throwing: error); return } 0020 let text = (request.results as? [VNRecognizedTextObservation])?.compactMap { $0.topCandidates(1).first?.string }.joined(separator: "\n") ?? "" 0021 continuation.resume(returning: text) 0022 } 0023 request.recognitionLevel = .accurate 0024 request.usesLanguageCorrection = true 0025 let supported = (try? request.supportedRecognitionLanguages()) ?? [] 0026 request.recognitionLanguages = languages.filter(supported.contains) 0027 if request.recognitionLanguages.isEmpty { request.recognitionLanguages = Array(supported.prefix(3)) } 0028 do { try VNImageRequestHandler(cgImage: cgImage).perform([request]) } 0029 catch { continuation.resume(throwing: error) } 0030 } 0031 } ```