@@ -104,18 +104,18 @@ public struct LaTeX: View {
104104
105105 /// The package's shared data cache.
106106 public static var dataCache : NSCache < NSString , NSData > {
107- Renderer . shared. dataCache
107+ Cache . shared. dataCache
108108 }
109109
110110#if os(macOS)
111111 /// The package's shared image cache.
112112 public static var imageCache : NSCache < NSString , NSImage > {
113- Renderer . shared. imageCache
113+ Cache . shared. imageCache
114114 }
115115#else
116116 /// The package's shared image cache.
117117 public static var imageCache : NSCache < NSString , UIImage > {
118- Renderer . shared. imageCache
118+ Cache . shared. imageCache
119119 }
120120#endif
121121
@@ -156,24 +156,8 @@ public struct LaTeX: View {
156156
157157 // MARK: Private properties
158158
159- /// The view's render state.
160- @StateObject private var renderState : LaTeXRenderState
161-
162- /// Renders the blocks synchronously.
163- ///
164- /// This will block whatever thread you call it on.
165- private var syncBlocks : [ ComponentBlock ] {
166- Renderer . shared. render (
167- blocks: Parser . parse ( unencodeHTML ? latex. htmlUnescape ( ) : latex, mode: parsingMode) ,
168- font: font ?? . body,
169- displayScale: displayScale,
170- texOptions: texOptions)
171- }
172-
173- /// The TeX options to use when submitting requests to the renderer.
174- private var texOptions : TeXInputProcessorOptions {
175- TeXInputProcessorOptions ( processEscapes: processEscapes, errorMode: errorMode)
176- }
159+ /// The view's renderer.
160+ @StateObject private var renderer : Renderer
177161
178162 // MARK: Initializers
179163
@@ -182,33 +166,35 @@ public struct LaTeX: View {
182166 /// - Parameter latex: The LaTeX input.
183167 public init ( _ latex: String ) {
184168 self . latex = latex
185- _renderState = StateObject ( wrappedValue: LaTeXRenderState ( latex: latex) )
169+ _renderer = StateObject ( wrappedValue: Renderer ( latex: latex) )
186170 }
187171
188172 // MARK: View body
189173
190174 public var body : some View {
191175 VStack ( spacing: 0 ) {
192- if renderState. rendered {
193- bodyWithBlocks ( renderState. blocks)
176+ if renderer. rendered {
177+ // If our blocks have been rendered, display them
178+ bodyWithBlocks ( renderer. blocks)
179+ }
180+ else if isCached ( ) {
181+ // If our blocks are cached, display them
182+ bodyWithBlocks ( renderSync ( ) )
194183 }
195184 else {
185+ // The view is not rendered nor cached
196186 switch renderingStyle {
197- case . empty:
198- Text ( " " )
199- . task ( render)
200- case . original:
201- Text ( latex)
202- . task ( render)
203- case . progress:
204- ProgressView ( )
205- . task ( render)
187+ case . empty, . original, . progress:
188+ // Render the components asynchronously
189+ loadingView ( ) . task ( renderAsync)
206190 case . wait:
207- bodyWithBlocks ( syncBlocks)
191+ // Render the components synchronously
192+ bodyWithBlocks ( renderSync ( ) )
208193 }
209194 }
210195 }
211- . animation ( renderingAnimation, value: renderState. rendered)
196+ . animation ( renderingAnimation, value: renderer. rendered)
197+ . environmentObject ( renderer)
212198 }
213199
214200}
@@ -220,7 +206,7 @@ extension LaTeX {
220206 /// Preloads the view's SVG and image data.
221207 public func preload( ) {
222208 Task {
223- await render ( )
209+ await renderAsync ( )
224210 }
225211 }
226212}
@@ -229,14 +215,45 @@ extension LaTeX {
229215
230216extension LaTeX {
231217
218+ /// Checks the renderer's caches for the current view.
219+ ///
220+ /// If this method returns `true`, then there is no need to do an async
221+ /// render.
222+ ///
223+ /// - Returns: A boolean indicating whether the components to the view are
224+ /// cached.
225+ private func isCached( ) -> Bool {
226+ renderer. isCached (
227+ unencodeHTML: unencodeHTML,
228+ parsingMode: parsingMode,
229+ processEscapes: processEscapes,
230+ errorMode: errorMode,
231+ font: font ?? . body,
232+ displayScale: displayScale)
233+ }
234+
232235 /// Renders the view's components.
233- @Sendable private func render( ) async {
234- await renderState. render (
236+ @Sendable private func renderAsync( ) async {
237+ await renderer. render (
238+ unencodeHTML: unencodeHTML,
239+ parsingMode: parsingMode,
240+ processEscapes: processEscapes,
241+ errorMode: errorMode,
242+ font: font ?? . body,
243+ displayScale: displayScale)
244+ }
245+
246+ /// Renders the view's components synchronously.
247+ ///
248+ /// - Returns: The rendered components.
249+ private func renderSync( ) -> [ ComponentBlock ] {
250+ renderer. renderSync (
235251 unencodeHTML: unencodeHTML,
236252 parsingMode: parsingMode,
237- font: font,
238- displayScale: displayScale,
239- texOptions: texOptions)
253+ processEscapes: processEscapes,
254+ errorMode: errorMode,
255+ font: font ?? . body,
256+ displayScale: displayScale)
240257 }
241258
242259 /// Creates the view's body based on its block mode.
@@ -254,6 +271,19 @@ extension LaTeX {
254271 }
255272 }
256273
274+ @MainActor @ViewBuilder private func loadingView( ) -> some View {
275+ switch renderingStyle {
276+ case . empty:
277+ Text ( " " )
278+ case . original:
279+ Text ( latex)
280+ case . progress:
281+ ProgressView ( )
282+ default :
283+ EmptyView ( )
284+ }
285+ }
286+
257287}
258288
259289@available ( iOS 16 . 1 , * )
0 commit comments