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( html: String, baseURL: URL?, style: RDEPUBTextRenderStyle ) throws -> RDEPUBRenderedChapterContent { #if canImport(DTCoreText) let markedHTML = RDEPUBTextRendererSupport.injectFragmentMarkers(into: html) guard let data = markedHTML.data(using: .utf8) else { throw RDEPUBTextRenderingError.htmlEncodingFailed } guard let rendered = makeAttributedString(from: data, baseURL: baseURL, style: style) else { return fallbackRenderedContent(for: markedHTML, style: style) } let attributedString = NSMutableAttributedString(attributedString: rendered) let fragmentOffsets = RDEPUBTextRendererSupport.extractFragmentOffsets(from: attributedString) RDEPUBTextRendererSupport.normalizeReadingAttributes(in: attributedString, style: style) return RDEPUBRenderedChapterContent(attributedString: attributedString, fragmentOffsets: fragmentOffsets) #else let markedHTML = RDEPUBTextRendererSupport.injectFragmentMarkers(into: html) return fallbackRenderedContent(for: markedHTML, style: style) #endif } private func fallbackRenderedContent(for html: String, style: RDEPUBTextRenderStyle) -> RDEPUBRenderedChapterContent { let attributedString = RDEPUBTextRendererSupport.fallbackAttributedString(for: html, style: style) let fragmentOffsets = RDEPUBTextRendererSupport.extractFragmentOffsets(from: attributedString) RDEPUBTextRendererSupport.normalizeReadingAttributes(in: attributedString, style: style) return RDEPUBRenderedChapterContent(attributedString: attributedString, fragmentOffsets: fragmentOffsets) } #if canImport(DTCoreText) private func makeAttributedString(from data: Data, baseURL: URL?, style: RDEPUBTextRenderStyle) -> NSAttributedString? { let builder = DTHTMLAttributedStringBuilder( html: data, options: dtOptions(baseURL: baseURL, style: style), documentAttributes: nil ) return builder?.generatedAttributedString() } private func dtOptions(baseURL: URL?, style: RDEPUBTextRenderStyle) -> [AnyHashable: Any] { 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 { options[NSBaseURLDocumentOption] = baseURL } if let textColor = style.textColor { options[DTDefaultTextColor] = textColor } return options } #endif }