SWIFT · NATIVE iOS · ZERO DEPENDENCIES

The featherweight
SVG renderer
for iOS.

ThinPath renders vector graphics with a flat arena architecture and zero allocation overhead — so your image-heavy app stays fast and your memory footprint stays tiny.

Install ThinPath View on GitHub ↗

// Swift Package Manager · iOS 13+ · MIT

FLAT ARENA ~1 alloc
nodes packed contiguously — cache-dense traversal
free slots — released in one instant

Renders what you draw.

// full SVG feature coverage

01
Shapes & Paths
Rect, circle, ellipse, line, polyline, polygon, and full path data including elliptical arcs.
02
Transforms
Translate, scale, rotate, skew, and nested matrix stacks — resolved on the flat tree.
03
Gradients & Patterns
Linear and radial gradients with stops and spread methods, plus pattern fills tiled via CGPattern.
04
Masks & Clips
Clip paths and alpha masks, with scratch surfaces clamped to the masked element's own bounds.
05
Text
Positioned text runs with prioritized font-family lookup and guaranteed system-font fallback.
06
Images
Embedded and local-file raster images, decoded at the target's device-pixel size — never upscaled past native resolution.

Why ThinPath

Built for developers who count allocations and measure frames.

~1 alloc
Memory efficient
The entire document tree lives in a handful of contiguous arrays. No per-node heap churn, no fragmentation.
0 deps
Pure Swift, native
No C++, no bridging, no third-party libraries. Drops into any iOS target with Swift Package Manager.
cache-dense
Fast traversal
Nodes are packed sequentially, so tree walks stay in cache instead of chasing pointers across the heap.
instant
Immediate release
When rendering finishes the arena's arrays are freed directly — no recursive teardown proportional to node count.

Up and running in a few lines.

Add the package, import the module, parse and render. No configuration, no bridging headers, no C++ toolchain.

.package(url: "https://github.com/sohandotgit/ThinPath.git", branch: "main")
ContentView.swift
import ThinPath

let svgData = try Data(contentsOf: iconURL)
let (document, errors) = parse(data: svgData)

let renderer = ThinPath()
if let image = renderer.render(
    document,
    size: CGSize(width: 64, height: 64),
    scale: 2
) // CGImage? — arena freed once `document` drops

The memory model, plainly.

Most renderers scatter node objects across the heap. ThinPath doesn't.

ARENA
One buffer, whole tree
Every element is an index into a flat array instead of a boxed object on the heap.
SCALE-AWARE
Images decode at draw size
Embedded and referenced raster images decode at the target's device-pixel size — never upscaled past native resolution.
O(1) FREE
Released all at once
No reference-counting cascade on teardown — the arena's arrays drop directly when you're done.