103 lines
3.6 KiB
Swift
103 lines
3.6 KiB
Swift
import UIKit
|
|
|
|
#if canImport(DTCoreText)
|
|
import DTCoreText
|
|
#endif
|
|
|
|
public struct RDEPUBDTCoreTextRenderer: RDEPUBTextRenderer {
|
|
public init() {}
|
|
|
|
public static var isAvailable: Bool {
|
|
#if canImport(DTCoreText)
|
|
return true
|
|
#else
|
|
return false
|
|
#endif
|
|
}
|
|
|
|
public func renderChapter(
|
|
request: RDEPUBTextChapterRenderRequest
|
|
) throws -> RDEPUBRenderedChapterContent {
|
|
#if canImport(DTCoreText)
|
|
let chapterContext = request.context
|
|
guard let data = chapterContext.html.data(using: .utf8) else {
|
|
throw RDEPUBTextRenderingError.htmlEncodingFailed
|
|
}
|
|
|
|
guard let rendered = makeAttributedString(from: data, request: request) else {
|
|
return fallbackRenderedContent(request: request)
|
|
}
|
|
|
|
let attributedString = NSMutableAttributedString(attributedString: rendered)
|
|
let fragmentOffsets = RDEPUBTextRendererSupport.extractFragmentOffsets(from: attributedString)
|
|
RDEPUBTextRendererSupport.normalizeReadingAttributes(in: attributedString, style: request.style)
|
|
return RDEPUBRenderedChapterContent(
|
|
attributedString: attributedString,
|
|
fragmentOffsets: fragmentOffsets,
|
|
resourceDiagnostics: chapterContext.resourceDiagnostics
|
|
)
|
|
#else
|
|
return fallbackRenderedContent(request: request)
|
|
#endif
|
|
}
|
|
|
|
public func renderChapter(
|
|
html: String,
|
|
baseURL: URL?,
|
|
style: RDEPUBTextRenderStyle
|
|
) throws -> RDEPUBRenderedChapterContent {
|
|
let request = RDEPUBTextRendererSupport.makeChapterRenderRequest(
|
|
href: "",
|
|
title: "",
|
|
rawHTML: html,
|
|
baseURL: baseURL,
|
|
style: style,
|
|
resourceResolver: nil
|
|
)
|
|
return try renderChapter(request: request)
|
|
}
|
|
|
|
private func fallbackRenderedContent(request: RDEPUBTextChapterRenderRequest) -> RDEPUBRenderedChapterContent {
|
|
let attributedString = RDEPUBTextRendererSupport.fallbackAttributedString(for: request.context.html, style: request.style)
|
|
let fragmentOffsets = RDEPUBTextRendererSupport.extractFragmentOffsets(from: attributedString)
|
|
RDEPUBTextRendererSupport.normalizeReadingAttributes(in: attributedString, style: request.style)
|
|
return RDEPUBRenderedChapterContent(
|
|
attributedString: attributedString,
|
|
fragmentOffsets: fragmentOffsets,
|
|
resourceDiagnostics: request.context.resourceDiagnostics
|
|
)
|
|
}
|
|
|
|
#if canImport(DTCoreText)
|
|
private func makeAttributedString(from data: Data, request: RDEPUBTextChapterRenderRequest) -> NSAttributedString? {
|
|
let builder = DTHTMLAttributedStringBuilder(
|
|
html: data,
|
|
options: dtOptions(request: request),
|
|
documentAttributes: nil
|
|
)
|
|
return builder?.generatedAttributedString()
|
|
}
|
|
|
|
private func dtOptions(request: RDEPUBTextChapterRenderRequest) -> [AnyHashable: Any] {
|
|
let style = request.style
|
|
var options: [AnyHashable: Any] = [
|
|
NSTextSizeMultiplierDocumentOption: 1.0,
|
|
DTDefaultFontFamily: style.font.familyName,
|
|
DTDefaultFontName: style.font.fontName,
|
|
DTDefaultFontSize: style.font.pointSize,
|
|
DTDefaultLineHeightMultiplier: max((style.font.lineHeight + style.lineSpacing) / max(style.font.lineHeight, 1), 1),
|
|
DTUseiOS6Attributes: true
|
|
]
|
|
|
|
if let baseURL = request.context.baseURL {
|
|
options[NSBaseURLDocumentOption] = baseURL
|
|
}
|
|
if let textColor = style.textColor {
|
|
options[DTDefaultTextColor] = textColor
|
|
}
|
|
|
|
return options
|
|
}
|
|
#endif
|
|
}
|