Skip to main content

Overview

MathRenderer is an enum that provides static methods for rendering LaTeX mathematical expressions into platform-native images. It uses the SwiftMath library for LaTeX parsing and rendering, with built-in caching for performance.

Definition

public enum MathRenderer
This is an enum with static methods only (no cases). It cannot be instantiated.

Methods

renderToImage(latex:fontSize:textColor:)
static func
Renders a LaTeX string to a platform-native image.
public static func renderToImage(
    latex: String,
    fontSize: CGFloat = 16,
    textColor: PlatformColor = .black
) -> PlatformImage?
Parameters:
  • latex: The LaTeX mathematical expression to render
  • fontSize: The font size in points (default: 16)
  • textColor: The text color for the rendered math
Returns: A rendered image, or nil if rendering failsPlatform Types:
  • iOS/visionOS: Returns UIImage?
  • macOS: Returns NSImage?

Type Aliases

#if canImport(UIKit)
    typealias PlatformImage = UIImage
    typealias PlatformColor = UIColor
#elseif canImport(AppKit)
    typealias PlatformImage = NSImage
    typealias PlatformColor = NSColor
#endif

LaTeX Preprocessing

Before rendering, LaTeX expressions are automatically preprocessed to improve compatibility with SwiftMath:

Command Replacements

OriginalReplacementReason
\dots\ldotsStandardize ellipsis
\implies\RightarrowArrow compatibility
\begin{align}\begin{aligned}SwiftMath support
\end{align}\end{aligned}SwiftMath support
\begin{align*}\begin{aligned}SwiftMath support
\end{align*}\end{aligned}SwiftMath support
\begin{cases}\left\{\begin{matrix}Cases environment
\end{cases}\end{matrix}\right.Cases environment
\dfrac\fracDisplay fraction
\boxed{...}... (content only)Remove boxing

Caching

The renderer maintains an internal cache for performance optimization:
private static let renderCache: NSCache<CacheKey, PlatformImage>

Cache Configuration

  • Type: NSCache
  • Count Limit: 256 images
  • Key Components: LaTeX string, font size, and resolved color (RGBA)

Cache Key

The cache key considers:
  • The exact LaTeX string
  • Font size in points
  • Text color components (R, G, B, A)
This ensures that the same math expression with different styling generates separate cache entries.

SwiftMath Integration

The renderer uses SwiftMath’s MTMathImage for LaTeX rendering:
let mathImage = MTMathImage(
    latex: processedLatex,
    fontSize: fontSize,
    textColor: resolvedTextColor,
    labelMode: .text
)
let (error, image) = mathImage.asImage()

Label Mode

The renderer uses .text label mode, which renders the expression in text style (inline math) rather than display style.

Image Template Mode

Rendered images are configured as templates to support dynamic colors:
let result = image
    .withRenderingMode(.alwaysTemplate)
    .withTintColor(.label)
This allows the image to adapt to light/dark mode automatically.

Error Handling

If rendering fails, the method:
  1. Prints an error message to the console
  2. Returns nil
print("[!] MathRenderer failed to render image for content: \(latex) \(error?.localizedDescription ?? "?")")

Example Usage

Basic Usage

let latex = "E = mc^2"
if let image = MathRenderer.renderToImage(latex: latex) {
    // Use the rendered image
    imageView.image = image
}

Custom Styling

let latex = "\\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}"
let image = MathRenderer.renderToImage(
    latex: latex,
    fontSize: 20,
    textColor: .systemBlue
)

Inline Math

let inlineMath = "x^2 + y^2 = r^2"
let icon = MathRenderer.renderToImage(
    latex: inlineMath,
    fontSize: 14,
    textColor: .label
)

Display Math with Alignment

let aligned = """
\\begin{aligned}
f(x) &= x^2 + 2x + 1 \\\\
     &= (x + 1)^2
\\end{aligned}
"""

let image = MathRenderer.renderToImage(
    latex: aligned,
    fontSize: 16
)

Common LaTeX Patterns

Fractions

\frac{a}{b}

Square Roots

\sqrt{x}
\sqrt[n]{x}

Summations and Integrals

\sum_{i=1}^{n} i^2
\int_{0}^{\infty} e^{-x} dx

Matrices

\begin{matrix}
a & b \\
c & d
\end{matrix}

Piecewise Functions

Note: \begin{cases} is automatically converted to matrix notation.
\begin{cases}
x^2 & \text{if } x \geq 0 \\
-x^2 & \text{if } x < 0
\end{cases}

Performance Considerations

Cache Hits

Repeated renders of the same expression are served from cache, providing near-instant results.

Color Resolution

Dynamic colors are resolved to their effective RGBA values for caching:
  • UIKit: Uses UITraitCollection.current for resolution
  • AppKit: Uses NSApp.effectiveAppearance for resolution
This ensures correct appearance in light/dark modes while maintaining cache effectiveness.

Memory Management

The NSCache automatically evicts entries under memory pressure. The 256-image limit balances memory usage with cache effectiveness.

Limitations

  1. SwiftMath Compatibility: Not all LaTeX commands are supported. The preprocessor handles common incompatibilities.
  2. Rendering Mode: Only text (inline) mode is used. Display mode with larger operators is not available.
  3. Advanced Features: Complex LaTeX packages (tikz, pgfplots, etc.) are not supported.
  4. Error Recovery: Failed renders return nil with no fallback.

Dependencies

  • SwiftMath: LaTeX parsing and rendering engine
  • Litext: Text layout framework

Build docs developers (and LLMs) love