Files
ReadViewSDK/Sources/RDAIReaderView/Core/RDAILocatorBuilder.swift
T
2026-07-27 21:43:13 +08:00

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
))
}
}