45 lines
1.6 KiB
Swift
45 lines
1.6 KiB
Swift
import Foundation
|
|
|
|
enum RDAILocatorBuilder {
|
|
static func makeLocator(
|
|
document: RDAIDocumentDescriptor,
|
|
snapshot: RDAIResourceSnapshot,
|
|
range: RDAITextRange
|
|
) -> RDAILocator? {
|
|
let matchingRuns = snapshot.locatorRuns.filter { $0.textRange.intersects(range) }
|
|
guard let first = matchingRuns.first else { return nil }
|
|
let anchor = mergedAnchor(matchingRuns) ?? first.anchor
|
|
return RDAILocator(
|
|
documentIdentifier: document.identifier,
|
|
resourceIdentifier: snapshot.descriptor.identifier,
|
|
textRange: range,
|
|
anchor: anchor,
|
|
sourceHash: snapshot.sourceHash
|
|
)
|
|
}
|
|
|
|
private static func mergedAnchor(_ runs: [RDAILocatorRun]) -> RDAIAnchor? {
|
|
guard !runs.isEmpty else { return nil }
|
|
let anchors = runs.compactMap { run -> RDAIPDFAnchor? in
|
|
if case .pdf(let anchor) = run.anchor { return anchor }
|
|
return nil
|
|
}
|
|
guard anchors.count == runs.count,
|
|
let first = anchors.first,
|
|
anchors.allSatisfy({ $0.pageIndex == first.pageIndex && $0.textSource == first.textSource }) else {
|
|
return nil
|
|
}
|
|
var rects: [RDAINormalizedRect] = []
|
|
for rect in anchors.flatMap(\.rects) where !rects.contains(rect) {
|
|
rects.append(rect)
|
|
}
|
|
let readingOrder = anchors.compactMap(\.readingOrder).min()
|
|
return .pdf(RDAIPDFAnchor(
|
|
pageIndex: first.pageIndex,
|
|
rects: rects,
|
|
textSource: first.textSource,
|
|
readingOrder: readingOrder
|
|
))
|
|
}
|
|
}
|