ChrisGVE/PlotSwift
Data visualization library for Swift
Overview
PlotSwift provides a low-level vector graphics system inspired by CoreGraphics but with a retained-mode architecture. All drawing operations are stored as commands that can be rendered at any resolution without quality loss.
Design Philosophy
- Vector-first rendering - All drawing operations stored as commands for scale-free output
- Multiple export formats - PNG, PDF, and SVG from the same drawing commands
- CoreGraphics based - Native rendering using Apple's graphics stack
- Foundation for plotting - Building block for data visualization (high-level plotting APIs coming in future versions)
Installation
Swift Package Manager
Add PlotSwift to your Package.swift:
dependencies: [
.package(url: "https://github.com/ChrisGVE/PlotSwift.git", from: "0.1.0")
]Or add it directly in Xcode via File > Add Package Dependencies.
Quick Start
Basic Drawing
import PlotSwift
// Create a drawing context
let ctx = DrawingContext()
// Draw shapes
ctx.setFillColor(.blue)
ctx.rect(50, 50, 200, 150)
ctx.fillPath()
ctx.setStrokeColor(.red)
ctx.setStrokeWidth(2.0)
ctx.circle(cx: 150, cy: 125, r: 50)
ctx.strokePath()
// Add text
ctx.text("Hello PlotSwift", x: 150, y: 220, style: TextStyle(
fontSize: 16,
fontWeight: .bold,
color: .black,
anchor: .middle
))
// Export to PNG
if let pngData = ctx.renderToPNG(size: CGSize(width: 400, height: 300)) {
// Use the PNG data
}Path Construction
let ctx = DrawingContext()
// Build a custom path
ctx.moveTo(100, 100)
ctx.lineTo(200, 100)
ctx.lineTo(200, 200)
ctx.lineTo(100, 200)
ctx.closePath()
ctx.setFillColor(Color(hex: "#3498db")!)
ctx.setStrokeColor(.black)
ctx.setStrokeWidth(2.0)
ctx.fillAndStrokePath()Curves and Arcs
let ctx = DrawingContext()
// Bezier curve
ctx.moveTo(50, 150)
ctx.curveTo(cp1x: 100, cp1y: 50, cp2x: 200, cp2y: 50, x: 250, y: 150)
ctx.setStrokeColor(.purple)
ctx.strokePath()
// Arc
ctx.arc(cx: 150, cy: 150, r: 80, startAngle: 0, endAngle: .pi * 1.5)
ctx.setStrokeColor(.orange)
ctx.setStrokeWidth(3.0)
ctx.strokePath()Transforms
let ctx = DrawingContext()
// Save state before transform
ctx.saveState()
// Apply transforms
ctx.translate(200, 200)
ctx.rotate(.pi / 4) // 45 degrees
ctx.scale(1.5, 1.5)
// Draw at transformed position
ctx.rect(-25, -25, 50, 50)
ctx.setFillColor(.green)
ctx.fillPath()
// Restore original state
ctx.restoreState()Export Formats
let ctx = DrawingContext()
// ... add drawing commands ...
let size = CGSize(width: 800, height: 600)
// PNG with custom scale (for retina displays)
let pngData = ctx.renderToPNG(size: size, scale: 2.0)
// PDF (vector format)
let pdfData = ctx.renderToPDF(size: size)
// SVG (web-friendly vector)
let svgString = ctx.renderToSVG(size: size)API Reference
Color
Create colors from RGB values, hex strings, or named colors:
let red = Color(red: 1, green: 0, blue: 0)
let blue = Color(hex: "#0000FF")!
let green = Color(name: "green")!
// Predefined colors
Color.black, Color.white, Color.red, Color.green, Color.blue
Color.yellow, Color.cyan, Color.magenta, Color.orange, Color.purple
Color.gray, Color.lightGray, Color.darkGray, Color.clearTextStyle
Configure text rendering:
let style = TextStyle(
fontFamily: "sans-serif",
fontSize: 14,
fontWeight: .bold, // .normal, .bold, .light
color: .black,
anchor: .middle // .start, .middle, .end
)LineStyle
Available line styles:
LineStyle.solid // Continuous line
LineStyle.dashed // Long dashes
LineStyle.dotted // Dots
LineStyle.dashDot // Alternating dash-dot
LineStyle.none // No lineMarkerStyle
Marker shapes for data points (rendering support coming soon):
MarkerStyle.circle, .square, .diamond
MarkerStyle.triangleUp, .triangleDown, .triangleLeft, .triangleRight
MarkerStyle.plus, .cross, .star, .dotDrawingContext Methods
Path Construction:
moveTo( x:, y:)- Start a new subpathlineTo( x:, y:)- Add line to current pathcurveTo(cp1x:, cp1y:, cp2x:, cp2y:, x:, y:)- Cubic Bezier curvequadCurveTo(cpx:, cpy:, x:, y:)- Quadratic Bezier curveclosePath()- Close the current subpath
Shapes:
rect( x:, y:, width:, height:)- Rectangleellipse(cx:, cy:, rx:, ry:)- Ellipsecircle(cx:, cy:, r:)- Circle (convenience)arc(cx:, cy:, r:, startAngle:, endAngle:, clockwise:)- Arc
Text:
text(_ string:, x:, y:, style:)- Draw text
Style State:
setStrokeColor(_ color:)- Set stroke colorsetStrokeWidth(_ width:)- Set line widthsetStrokeStyle(_ style:)- Set dash patternsetFillColor(_ color:)- Set fill colorsetAlpha(_ alpha:)- Set global alpha
Drawing Operations:
strokePath()- Stroke the current pathfillPath()- Fill the current pathfillAndStrokePath()- Fill and stroke
Transforms:
translate( tx:, ty:)- Translate coordinate systemscale( sx:, sy:)- Scale coordinate systemrotate(_ angle:)- Rotate (radians)pushTransform(_ transform:)- Push custom transformpopTransform()- Pop transform
State Management:
saveState()- Save graphics staterestoreState()- Restore graphics stateclear()- Clear all commands
Export:
renderToPNG(size:, scale:)- Export to PNG datarenderToPDF(size:)- Export to PDF datarenderToSVG(size:)- Export to SVG string
Current Limitations
- SVG export: Transform nesting is approximate; deeply nested transforms may accumulate rounding. Clip regions use random IDs that may collide in very large documents.
- Text measurement: Text bounding boxes are estimated from optical bounds, which can be inaccurate for some fonts and scripts. Y-label rotation is simulated via positioning rather than actual SVG/CG rotation.
- Logarithmic scale:
LogTransformclamps non-positive values silently. Tick generation for log scales uses the linear nice-number algorithm rather than decade-based ticks. - Animation: Frame-by-frame only; no native video encoding. Use the PNG frame sequence with an external tool (e.g., FFmpeg) for video output.
- Conditional integration: NumericSwift and ArraySwift extensions are compiled only when those packages are present; they are not testable in standalone builds.
- Bounds calculation: Stroke width expansion and transform-aware bounds are best-effort approximations; complex transform chains may undercount.
Requirements
- Swift 5.9+
- iOS 15.0+ / macOS 12.0+ / watchOS 8.0+ / tvOS 15.0+ / visionOS 1.0+
- Frameworks: CoreGraphics, CoreText, ImageIO
License
PlotSwift is available under the MIT License. See the LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit issues and pull requests.
Package Metadata
Repository: ChrisGVE/PlotSwift
Stars: 2
Forks: 0
Open issues: 0
Default branch: main
Primary language: swift
License: MIT
README: README.md