Thanks to visit codestin.com
Credit goes to github.com

Skip to content

eliheuer/designbot

Repository files navigation

DesignBot

A Rust-based 2D graphics generation tool inspired by DrawBot and Processing. Create vector graphics, images, and animations through Rust code. This should be a fun way for type designers, graphic designers, artists, and students to learn Rust programming.

Image

Features

  • 🎨 DrawBot-inspired API - Familiar drawing primitives (rect, oval, line, polygon, etc)
  • 🎯 Self-contained - Zero system dependencies
  • 📦 Multiple output formats - PNG (more coming: SVG, PDF, GIF, MP4)

Installation

Recommended: Install from Git

This is the easiest way to install and ensures you get the latest version:

cargo install --git https://github.com/eliheuer/designbot designbot-cli

For Development: Install from Local Source

If you're contributing to DesignBot or testing local changes:

# Clone the repository
git clone https://github.com/eliheuer/designbot
cd designbot

# Install the CLI (will use git dependencies for user scripts)
cargo install --path designbot-cli --force

Important: After making local changes, you must push them to GitHub's main branch before the installed CLI can use them when compiling user scripts.

After installation, the designbot command will be available in your terminal (usually in ~/.cargo/bin/designbot).

Performance Notes

First run: The CLI will compile dependencies (takes ~1-2 minutes) Subsequent runs: Uses a persistent cache at ~/.designbot/cache (~0.5 seconds)

To clear the cache if needed:

rm -rf ~/.designbot/cache

Quick Start

Using the CLI

# Create a simple design script
designbot --render my_design.rs --output my_design.png

Testing Fonts

Perfect for type designers testing fonts:

// font_test.rs
use designbot::prelude::*;

fn main() {
    let mut ctx = Canvas::new(1200.0, 800.0);
    let mut renderer = Renderer::new(1200, 800);

    // Load your font
    renderer.load_font("fonts/MyFont-Regular.ttf").unwrap();

    ctx.background(Color::rgb(255, 255, 255));
    ctx.fill(Color::rgb(0, 0, 0));
    ctx.font("MyFont");

    // Test different sizes
    ctx.font_size(72.0);
    ctx.text("The quick brown fox", 50.0, 100.0);

    ctx.font_size(48.0);
    ctx.text("jumps over the lazy dog", 50.0, 200.0);

    ctx.font_size(24.0);
    ctx.text("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 50.0, 300.0);
    ctx.text("abcdefghijklmnopqrstuvwxyz", 50.0, 350.0);
    ctx.text("0123456789 !@#$%^&*()", 50.0, 400.0);

    renderer.render_to_png(&ctx, "font_test.png").unwrap();
}

Run with:

designbot --render font_test.rs --output font_test.png

Using Examples (For Development)

Examples output to the current directory:

# Run from the designbot git repo
cd designbot
cargo run --example basic_shapes

This generates basic_shapes.png in your current directory.

Usage Examples

Simple Script (CLI Auto-wraps)

Create a file my_design.rs:

use designbot::prelude::*;

// Just drawing commands - no main function needed
ctx.fill(Color::rgb(255, 100, 100));
ctx.rect(100.0, 100.0, 400.0, 400.0);

ctx.fill(Color::rgb(100, 255, 100));
ctx.oval(200.0, 200.0, 200.0, 200.0);

Run with:

designbot --render my_design.rs --output my_design.png

Full Script (Complete Control)

Create a file custom_design.rs:

use designbot::prelude::*;

fn main() {
    let mut ctx = Canvas::new(800.0, 600.0);

    // Draw shapes
    ctx.fill(Color::rgb(255, 200, 100));
    ctx.rect(100.0, 100.0, 600.0, 400.0);

    // Render
    let renderer = Renderer::new(800, 600);
    renderer.render_to_png(&ctx, "output.png").unwrap();
}

Run with:

designbot --render custom_design.rs --output custom.png

As a Library (Example Files)

Create examples in examples/ directory:

// examples/my_example.rs
use designbot::prelude::*;

fn main() {
    let mut ctx = Canvas::new(600.0, 600.0);

    ctx.fill(Color::rgb(100, 200, 255));
    ctx.oval(100.0, 100.0, 400.0, 400.0);

    // Output to current directory
    let renderer = Renderer::new(600, 600);
    renderer.render_to_png(&ctx, "my_example.png").unwrap();

    println!("Rendered my_example.png");
}

Run with:

cargo run --example my_example
# Generates my_example.png in current directory

API Overview

Canvas Management

let mut ctx = Canvas::new(800.0, 600.0);

Drawing Primitives

ctx.rect(x, y, width, height);
ctx.oval(x, y, width, height);
ctx.line(x1, y1, x2, y2);
ctx.polygon(&[(x1, y1), (x2, y2), ...], close);

Colors and Styling

ctx.fill(Color::rgb(255, 0, 0));
ctx.stroke(Color::black());
ctx.stroke_width(2.0);
ctx.no_fill();
ctx.no_stroke();

Transformations

ctx.save();           // Push state
ctx.translate(x, y);
ctx.rotate(degrees);
ctx.scale(factor);
ctx.restore();        // Pop state

Text Rendering

// Set font and size
ctx.font("Arial");
ctx.font_size(48.0);
ctx.fill(Color::black());

// Draw single-line text
ctx.text("Hello World", 100.0, 100.0);

// Draw multi-line text box with word wrapping
ctx.text_box("Long text that wraps...", 100.0, 200.0, 400.0, 200.0);

Custom Font Loading

// Load custom fonts from files
let mut renderer = Renderer::new(800, 600);
renderer.load_font("fonts/MyFont-Regular.ttf").unwrap();
renderer.load_font("fonts/MyFont-Bold.ttf").unwrap();

// Use the loaded fonts
ctx.font("MyFont");
ctx.text("Custom Font", 100.0, 100.0);

// System fonts still work too
ctx.font("Arial");
ctx.text("System Font", 100.0, 200.0);

Rendering

let renderer = Renderer::new(width, height);
renderer.render_to_png(&ctx, "output.png").unwrap();

Project Structure

designbot/
├── designbot/           # Core library (Canvas, Colors, Shapes)
├── designbot-render/    # Rendering backend (Vello integration)
├── designbot-cli/       # CLI application
├── examples/            # Example scripts with outputs
└── docs/                # Documentation and project plan

Technology Stack

  • vello_cpu - CPU-based 2D rendering (faster for reading back to CPU memory)
  • AnyRender - Portable rendering abstraction across backends
  • Kurbo - 2D curves and paths (including native Ellipse type)
  • Peniko - Styling primitives
  • wgpu - GPU access
  • image - Image encoding/decoding

Current Status

Phase 1 Complete: Basic rendering infrastructure

  • Project structure and workspace
  • CLI with script compilation
  • Vello renderer integration
  • PNG output
  • Canvas management

Phase 2 Complete: Core drawing API

  • Shape primitives (rect, oval, line, polygon)
  • Fill and stroke colors
  • Graphics state stack (save/restore)
  • Basic transformations (translate, rotate, scale)
  • Text rendering with Parley
  • Custom font loading
  • Path operations (bezier curves)

🔧 Current Improvements:

  • Migrating to vello_cpu for better CPU readback performance
  • Integrating AnyRender for portable rendering across backends
  • Using Kurbo's native Ellipse type for oval rendering

🔜 Coming Soon:

  • Gradients
  • Image placement
  • SVG/PDF output
  • Animation support
  • Advanced path operations

See docs/PROJECT_PLAN.md for the full roadmap.

Development

# Run tests
cargo test

# Build all packages
cargo build --workspace

# Run clippy
cargo clippy --workspace

# Format code
cargo fmt --all

Examples

Check out the examples/ directory for more:

  • basic_shapes.rs - All primitive shapes (rect, oval, line, polygon)
  • basic_text.rs - Text rendering and custom font loading
  • grid.rs - Using state transformations for layout
  • More examples coming soon!

Font Setup for Examples

To run the text examples with custom fonts:

  1. Create examples/fonts/ directory (already exists)
  2. Download fonts (e.g., Inter) and place .ttf files in the directory
  3. See examples/fonts/README.md for detailed setup instructions

The examples will fall back to system fonts if custom fonts aren't found.

License

Apache-2.0

Acknowledgments

Inspired by DrawBot by Just van Rossum and Frederik Berlaen. Built on crates from the Linebender ecosystem.

About

Like DrawBot but in Rust. Create graphics with code.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages