Skip to content

yandex/cggen

Repository files navigation

cggen

CI

Swift Package Manager plugin for generating optimized Swift drawing code from SVG and PDF files.

Instead of bundling vector assets as resources, cggen compiles them into compressed bytecode and generates Swift code that executes drawing operations using Core Graphics, resulting in smaller app bundles and better performance.

Features

  • Swift Package Manager Plugin: Automatic code generation during build
  • SVG and PDF Support: Convert vector graphics from both formats
  • Bytecode Compilation: Generates compressed bytecode for efficient rendering
  • Memory-Optimized Drawing: Equatable/Hashable Drawing struct with minimal memory footprint
  • SwiftUI Integration: Direct usage of drawings as SwiftUI views
  • Cross-Platform Support: Works with UIKit, AppKit, and SwiftUI
  • Content Mode Support: Comprehensive scaling options for different use cases

Installation

Add cggen as a dependency to your Package.swift:

dependencies: [
  .package(url: "https://github.com/yandex/cggen", from: "1.0.0")
]

Add the plugin to your target and include runtime dependency:

.target(
  name: "YourTarget", 
  dependencies: [
    .product(name: "cggen-runtime-support", package: "cggen")
  ],
  plugins: [
    .plugin(name: "cggen-spm-plugin", package: "cggen")
  ]
)

Important: Your target must depend on cggen-runtime-support library to provide the bytecode execution runtime.

Xcode Project Integration (Beta)

cggen also supports Xcode projects through Build Tool Plug-ins:

  1. Add the cggen Swift package to your Xcode project
  2. In your target's Build Phases, add cggen-spm-plugin to "Build Tool Plug-ins"
  3. Add cggen-runtime-support to your target's frameworks

⚠️ Known Issue: When using cggen with Xcode projects, SVG/PDF source files are currently included in the app bundle alongside the generated code. This is a known limitation with Xcode's build system. To avoid increased app size:

  • Manually remove SVG/PDF files from "Copy Bundle Resources" build phase
  • Keep them only as inputs to the build tool plugin

This issue does not affect Swift Package Manager targets.

Usage

Basic Setup

  1. Place your .svg or .pdf files in your target's source directory
  2. The plugin automatically finds and processes these files during build
  3. Generated Swift code provides Drawing namespace with your graphics

Generated API

For SVG files like icon.svg, logo.svg, cggen generates:

// Drawing namespace with static properties
extension Drawing {
  static let icon = Drawing(
    width: 24.0,
    height: 24.0,
    bytecodeArray: mergedBytecodes,
    decompressedSize: 1234,
    startIndex: 0,
    endIndex: 567
  )
  
  static let logo = Drawing(/* ... */)
}

The Drawing struct conforms to Equatable and Hashable protocols.

SwiftUI Usage

Use drawings directly as views:

import SwiftUI
import CGGenRuntimeSupport

struct ContentView: View {
  var body: some View {
    VStack {
      Drawing.icon
        .foregroundColor(.blue)
        .frame(width: 44, height: 44)
      
      Drawing.logo
        .shadow(radius: 5)
    }
  }
}

UIKit/AppKit Usage

Create platform images using various APIs:

import UIKit
import CGGenRuntimeSupport

// Using KeyPath API (Swift 6.1+)
let iconImage = UIImage.draw(\.icon)
let scaledIcon = UIImage.draw(\.icon, scale: 2.0)

// Using direct initializers
let logoImage = UIImage(drawing: .logo)
let thumbnail = UIImage(
  drawing: .logo,
  size: CGSize(width: 100, height: 100),
  contentMode: .aspectFit
)

// AppKit (macOS)
let nsIcon = NSImage.draw(\.icon)
let nsLogo = NSImage(drawing: .logo)

Content Modes

Control how drawings scale to fit target sizes:

public enum DrawingContentMode {
  case scaleToFill    // Stretches to fill
  case aspectFit      // Fits within bounds
  case aspectFill     // Fills bounds, may crop
  case center         // Original size, centered
  case top, bottom, left, right
  case topLeft, topRight, bottomLeft, bottomRight
}

// Example: Create app icons at various sizes
let icon = UIImage(
  drawing: .appIcon,
  size: CGSize(width: 128, height: 128),
  contentMode: .aspectFit
)

Core Graphics Direct Drawing

Draw directly to a graphics context:

if let context = UIGraphicsGetCurrentContext() {
  // Draw at origin
  Drawing.logo.draw(in: context)
  
  // Draw at specific position
  context.saveGState()
  context.translateBy(x: 100, y: 50)
  Drawing.icon.draw(in: context)
  context.restoreGState()
}

Path Extraction API (Work in Progress)

cggen can extract vector paths for use in animations, clipping, or custom rendering:

// Extract path from generated code
let starPath = Drawing.Path.star

For more details, see Path Generation Guide.

Demo Applications

Demo

A comprehensive demo app showcasing all cggen features:

  • Location: Demo/
  • Platforms: macOS and iOS
  • Features: SwiftUI, AppKit, and UIKit examples with interactive playground
  • Build: Open Demo/Demo.xcodeproj in Xcode

Plugin Demo

Command-line demonstration of the plugin functionality:

  • Location: Sources/plugin-demo/
  • Features: Shows all API patterns and platform-specific usage
  • Run: swift run plugin-demo

CLI Usage

The underlying CLI tool can be used directly for custom workflows:

swift run cggen --swift-output Generated.swift input.svg input.pdf

CLI Options

  • --swift-output <path>: Generate Swift code to specified file
  • --generation-style <style>: Either "plain" or "swift-friendly" (default: "plain")
  • --objc-prefix <prefix>: Add prefix to generated function names
  • --module-name <name>: Module name for generated code
  • --objc-header <path>: Generate Objective-C header file
  • --objc-impl <path>: Generate Objective-C implementation file
  • --verbose: Enable debug output

Architecture

cggen uses a sophisticated compilation approach:

  1. Parsing: SVG and PDF files are parsed into internal representations
  2. Intermediate Representation: Graphics operations are converted to DrawRoute/PathRoutine structures
  3. Bytecode Generation: Operations are compiled into compressed bytecode arrays (LZFSE compression)
  4. Code Generation: Swift code is generated with the Drawing namespace
  5. Runtime Execution: CGGenRuntimeSupport provides bytecode execution

Documentation

About

Tool for generating Core Graphics code from vector image files

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 9